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 1FFADCA9EC9 for ; Fri, 1 Nov 2019 06:28:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CCF9B21855 for ; Fri, 1 Nov 2019 06:28:14 +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="Vaw3+tcm"; dkim=fail reason="key not found in DNS" (0-bit key) header.d=codeaurora.org header.i=@codeaurora.org header.b="DjwIyBjR" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729894AbfKAG2L (ORCPT ); Fri, 1 Nov 2019 02:28:11 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:46208 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727383AbfKAG2K (ORCPT ); Fri, 1 Nov 2019 02:28:10 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 738DC60EE6; Fri, 1 Nov 2019 06:28:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572589689; bh=XDDayIt0SyW3eZnIq3LHOzJB47k4lBZqsbBwsxBkEA8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Vaw3+tcmYvlV6PQDJuQq3vdIebTa4foo+e9/fVoKJcHD90qkJ23SoJR6ccZFzythN Shx5GhmTQDAjoFZKFPq4AaEVmbZ+jiRO5SuewBSOqDvjO5hEoIQqEr3xualHQlrirq OAv1gM//KNOw683XJlbN2Bhi00kXCr9r+FUMhLdI= 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 AB02F60DE9; Fri, 1 Nov 2019 06:27:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572589685; bh=XDDayIt0SyW3eZnIq3LHOzJB47k4lBZqsbBwsxBkEA8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DjwIyBjR2t9/xdbjYNouEj3rPbwX6Lao78csW4ZBZA8vBhS4ik380k3KlD2mfNxGv fuA+auBz1RS5hP7AxGelJum3EBHkbbseIqmSNrk49iuhpBWlBH6s2LKeThsguoe5RE r7JIeRzpihT3ctldWnSyD5EaQOC2TA+KsEFxHVjs= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org AB02F60DE9 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 5/8] backlight: qcom-wled: Restructure the driver for WLED3. Date: Fri, 1 Nov 2019 11:57:01 +0530 Message-Id: <1572589624-6095-6-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 Restructure the driver to add the support for new WLED peripherals. Signed-off-by: Kiran Gunda Acked-by: Daniel Thompson --- drivers/video/backlight/qcom-wled.c | 373 ++++++++++++++++++++++-------------- 1 file changed, 234 insertions(+), 139 deletions(-) diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c index f191242..45eeda4 100644 --- a/drivers/video/backlight/qcom-wled.c +++ b/drivers/video/backlight/qcom-wled.c @@ -7,59 +7,71 @@ #include #include #include +#include #include /* From DT binding */ +#define WLED_MAX_STRINGS 4 + #define WLED_DEFAULT_BRIGHTNESS 2048 #define WLED3_SINK_REG_BRIGHT_MAX 0xFFF -#define WLED3_CTRL_REG_VAL_BASE 0x40 /* WLED3 control registers */ #define WLED3_CTRL_REG_MOD_EN 0x46 -#define WLED3_CTRL_REG_MOD_EN_BIT BIT(7) #define WLED3_CTRL_REG_MOD_EN_MASK BIT(7) +#define WLED3_CTRL_REG_MOD_EN_SHIFT 7 #define WLED3_CTRL_REG_FREQ 0x4c -#define WLED3_CTRL_REG_FREQ_MASK 0x0f +#define WLED3_CTRL_REG_FREQ_MASK GENMASK(3, 0) #define WLED3_CTRL_REG_OVP 0x4d -#define WLED3_CTRL_REG_OVP_MASK 0x03 +#define WLED3_CTRL_REG_OVP_MASK GENMASK(1, 0) #define WLED3_CTRL_REG_ILIMIT 0x4e -#define WLED3_CTRL_REG_ILIMIT_MASK 0x07 +#define WLED3_CTRL_REG_ILIMIT_MASK GENMASK(2, 0) /* WLED3 sink registers */ #define WLED3_SINK_REG_SYNC 0x47 -#define WLED3_SINK_REG_SYNC_MASK 0x07 -#define WLED3_SINK_REG_SYNC_LED1 BIT(0) -#define WLED3_SINK_REG_SYNC_LED2 BIT(1) -#define WLED3_SINK_REG_SYNC_LED3 BIT(2) -#define WLED3_SINK_REG_SYNC_ALL 0x07 #define WLED3_SINK_REG_SYNC_CLEAR 0x00 #define WLED3_SINK_REG_CURR_SINK 0x4f -#define WLED3_SINK_REG_CURR_SINK_MASK 0xe0 -#define WLED3_SINK_REG_CURR_SINK_SHFT 0x05 +#define WLED3_SINK_REG_CURR_SINK_MASK GENMASK(7, 5) +#define WLED3_SINK_REG_CURR_SINK_SHFT 5 -/* WLED3 per-'string' registers below */ -#define WLED3_SINK_REG_STR_OFFSET 0x10 +/* WLED3 specific per-'string' registers below */ +#define WLED3_SINK_REG_BRIGHT(n) (0x40 + n) -#define WLED3_SINK_REG_STR_MOD_EN_BASE 0x60 +#define WLED3_SINK_REG_STR_MOD_EN(n) (0x60 + (n * 0x10)) #define WLED3_SINK_REG_STR_MOD_MASK BIT(7) -#define WLED3_SINK_REG_STR_MOD_EN BIT(7) -#define WLED3_SINK_REG_STR_FULL_SCALE_CURR 0x62 -#define WLED3_SINK_REG_STR_FULL_SCALE_CURR_MASK 0x1f +#define WLED3_SINK_REG_STR_FULL_SCALE_CURR(n) (0x62 + (n * 0x10)) +#define WLED3_SINK_REG_STR_FULL_SCALE_CURR_MASK GENMASK(4, 0) -#define WLED3_SINK_REG_STR_MOD_SRC_BASE 0x63 -#define WLED3_SINK_REG_STR_MOD_SRC_MASK 0x01 +#define WLED3_SINK_REG_STR_MOD_SRC(n) (0x63 + (n * 0x10)) +#define WLED3_SINK_REG_STR_MOD_SRC_MASK BIT(0) #define WLED3_SINK_REG_STR_MOD_SRC_INT 0x00 #define WLED3_SINK_REG_STR_MOD_SRC_EXT 0x01 -#define WLED3_SINK_REG_STR_CABC_BASE 0x66 +#define WLED3_SINK_REG_STR_CABC(n) (0x66 + (n * 0x10)) #define WLED3_SINK_REG_STR_CABC_MASK BIT(7) -#define WLED3_SINK_REG_STR_CABC_EN BIT(7) + +struct wled_var_cfg { + const u32 *values; + u32 (*fn)(u32); + int size; +}; + +struct wled_u32_opts { + const char *name; + u32 *val_ptr; + const struct wled_var_cfg *cfg; +}; + +struct wled_bool_opts { + const char *name; + bool *val_ptr; +}; struct wled_config { u32 boost_i_limit; @@ -67,132 +79,179 @@ struct wled_config { u32 switch_freq; u32 num_strings; u32 string_i_limit; + u32 enabled_strings[WLED_MAX_STRINGS]; bool cs_out_en; bool ext_gen; - bool cabc_en; + bool cabc; }; struct wled { const char *name; + struct device *dev; struct regmap *regmap; - u16 addr; + u16 ctrl_addr; + u16 max_string_count; + u32 brightness; + u32 max_brightness; struct wled_config cfg; + int (*wled_set_brightness)(struct wled *wled, u16 brightness); }; +static int wled3_set_brightness(struct wled *wled, u16 brightness) +{ + int rc, i; + u8 v[2]; + + 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->ctrl_addr + + WLED3_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; + + rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + + WLED3_CTRL_REG_MOD_EN, + WLED3_CTRL_REG_MOD_EN_MASK, + val << WLED3_CTRL_REG_MOD_EN_SHIFT); + return rc; +} + +static int wled_sync_toggle(struct wled *wled) +{ + int rc; + unsigned int mask = GENMASK(wled->max_string_count - 1, 0); + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_SINK_REG_SYNC, + mask, mask); + if (rc < 0) + return rc; + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_SINK_REG_SYNC, + mask, WLED3_SINK_REG_SYNC_CLEAR); + + return rc; +} + static int wled_update_status(struct backlight_device *bl) { struct wled *wled = bl_get_data(bl); - u16 val = bl->props.brightness; - u8 ctrl = 0; - int rc; - int i; + u16 brightness = bl->props.brightness; + int rc = 0; if (bl->props.power != FB_BLANK_UNBLANK || bl->props.fb_blank != FB_BLANK_UNBLANK || bl->props.state & BL_CORE_FBBLANK) - val = 0; - - if (val != 0) - ctrl = WLED3_CTRL_REG_MOD_EN_BIT; + brightness = 0; - rc = regmap_update_bits(wled->regmap, - wled->addr + WLED3_CTRL_REG_MOD_EN, - WLED3_CTRL_REG_MOD_EN_MASK, ctrl); - if (rc) - return rc; + if (brightness) { + rc = wled->wled_set_brightness(wled, brightness); + if (rc < 0) { + dev_err(wled->dev, "wled failed to set brightness rc:%d\n", + rc); + return rc; + } - for (i = 0; i < wled->cfg.num_strings; ++i) { - u8 v[2] = { val & 0xff, (val >> 8) & 0xf }; + rc = wled_sync_toggle(wled); + if (rc < 0) { + dev_err(wled->dev, "wled sync failed rc:%d\n", rc); + return rc; + } + } - rc = regmap_bulk_write(wled->regmap, - wled->addr + WLED3_CTRL_REG_VAL_BASE + 2 * i, - v, 2); - if (rc) + if (!!brightness != !!wled->brightness) { + rc = wled_module_enable(wled, !!brightness); + if (rc < 0) { + dev_err(wled->dev, "wled enable failed rc:%d\n", rc); return rc; + } } - rc = regmap_update_bits(wled->regmap, - wled->addr + WLED3_SINK_REG_SYNC, - WLED3_SINK_REG_SYNC_MASK, WLED3_SINK_REG_SYNC_ALL); - if (rc) - return rc; + wled->brightness = brightness; - rc = regmap_update_bits(wled->regmap, - wled->addr + WLED3_SINK_REG_SYNC, - WLED3_SINK_REG_SYNC_MASK, WLED3_SINK_REG_SYNC_CLEAR); return rc; } -static int wled_setup(struct wled *wled) +static int wled3_setup(struct wled *wled) { - int rc; - int i; + u16 addr; + u8 sink_en = 0; + int rc, i, j; rc = regmap_update_bits(wled->regmap, - wled->addr + WLED3_CTRL_REG_OVP, - WLED3_CTRL_REG_OVP_MASK, wled->cfg.ovp); + wled->ctrl_addr + WLED3_CTRL_REG_OVP, + WLED3_CTRL_REG_OVP_MASK, wled->cfg.ovp); if (rc) return rc; rc = regmap_update_bits(wled->regmap, - wled->addr + WLED3_CTRL_REG_ILIMIT, - WLED3_CTRL_REG_ILIMIT_MASK, wled->cfg.boost_i_limit); + wled->ctrl_addr + WLED3_CTRL_REG_ILIMIT, + WLED3_CTRL_REG_ILIMIT_MASK, + wled->cfg.boost_i_limit); if (rc) return rc; rc = regmap_update_bits(wled->regmap, - wled->addr + WLED3_CTRL_REG_FREQ, - WLED3_CTRL_REG_FREQ_MASK, wled->cfg.switch_freq); + wled->ctrl_addr + WLED3_CTRL_REG_FREQ, + WLED3_CTRL_REG_FREQ_MASK, + wled->cfg.switch_freq); if (rc) return rc; - if (wled->cfg.cs_out_en) { - u8 all = (BIT(wled->cfg.num_strings) - 1) - << WLED3_SINK_REG_CURR_SINK_SHFT; - - rc = regmap_update_bits(wled->regmap, - wled->addr + WLED3_SINK_REG_CURR_SINK, - WLED3_SINK_REG_CURR_SINK_MASK, all); - if (rc) - return rc; - } - for (i = 0; i < wled->cfg.num_strings; ++i) { - u16 addr = wled->addr + WLED3_SINK_REG_STR_OFFSET * i; - - rc = regmap_update_bits(wled->regmap, - addr + WLED3_SINK_REG_STR_MOD_EN_BASE, - WLED3_SINK_REG_STR_MOD_MASK, - WLED3_SINK_REG_STR_MOD_EN); + j = wled->cfg.enabled_strings[i]; + addr = wled->ctrl_addr + WLED3_SINK_REG_STR_MOD_EN(j); + rc = regmap_update_bits(wled->regmap, addr, + WLED3_SINK_REG_STR_MOD_MASK, + WLED3_SINK_REG_STR_MOD_MASK); if (rc) return rc; if (wled->cfg.ext_gen) { - rc = regmap_update_bits(wled->regmap, - addr + WLED3_SINK_REG_STR_MOD_SRC_BASE, - WLED3_SINK_REG_STR_MOD_SRC_MASK, - WLED3_SINK_REG_STR_MOD_SRC_EXT); + addr = wled->ctrl_addr + WLED3_SINK_REG_STR_MOD_SRC(j); + rc = regmap_update_bits(wled->regmap, addr, + WLED3_SINK_REG_STR_MOD_SRC_MASK, + WLED3_SINK_REG_STR_MOD_SRC_EXT); if (rc) return rc; } - rc = regmap_update_bits(wled->regmap, - addr + WLED3_SINK_REG_STR_FULL_SCALE_CURR, - WLED3_SINK_REG_STR_FULL_SCALE_CURR_MASK, - wled->cfg.string_i_limit); + addr = wled->ctrl_addr + WLED3_SINK_REG_STR_FULL_SCALE_CURR(j); + rc = regmap_update_bits(wled->regmap, addr, + WLED3_SINK_REG_STR_FULL_SCALE_CURR_MASK, + wled->cfg.string_i_limit); if (rc) return rc; - rc = regmap_update_bits(wled->regmap, - addr + WLED3_SINK_REG_STR_CABC_BASE, - WLED3_SINK_REG_STR_CABC_MASK, - wled->cfg.cabc_en ? - WLED3_SINK_REG_STR_CABC_EN : 0); + addr = wled->ctrl_addr + WLED3_SINK_REG_STR_CABC(j); + rc = regmap_update_bits(wled->regmap, addr, + WLED3_SINK_REG_STR_CABC_MASK, + wled->cfg.cabc ? + WLED3_SINK_REG_STR_CABC_MASK : 0); if (rc) return rc; + + sink_en |= BIT(j + WLED3_SINK_REG_CURR_SINK_SHFT); } + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_SINK_REG_CURR_SINK, + WLED3_SINK_REG_CURR_SINK_MASK, sink_en); + if (rc) + return rc; + return 0; } @@ -200,17 +259,12 @@ static int wled_setup(struct wled *wled) .boost_i_limit = 3, .string_i_limit = 20, .ovp = 2, + .num_strings = 3, .switch_freq = 5, - .num_strings = 0, .cs_out_en = false, .ext_gen = false, - .cabc_en = false, -}; - -struct wled_var_cfg { - const u32 *values; - u32 (*fn)(u32); - int size; + .cabc = false, + .enabled_strings = {0, 1, 2, 3}, }; static const u32 wled3_boost_i_limit_values[] = { @@ -255,7 +309,11 @@ static u32 wled3_switch_freq_values_fn(u32 idx) .size = 26, }; -static u32 wled3_values(const struct wled_var_cfg *cfg, u32 idx) +static const struct wled_var_cfg wled3_string_cfg = { + .size = 8, +}; + +static u32 wled_values(const struct wled_var_cfg *cfg, u32 idx) { if (idx >= cfg->size) return UINT_MAX; @@ -266,68 +324,75 @@ static u32 wled3_values(const struct wled_var_cfg *cfg, u32 idx) return idx; } -static int wled_configure(struct wled *wled, struct device *dev) +static int wled_configure(struct wled *wled, int version) { struct wled_config *cfg = &wled->cfg; - u32 val; - int rc; - u32 c; - int i; - int j; - - const struct { - const char *name; - u32 *val_ptr; - const struct wled_var_cfg *cfg; - } u32_opts[] = { + struct device *dev = wled->dev; + const __be32 *prop_addr; + u32 size, val, c, string_len; + int rc, i, j; + + const struct wled_u32_opts *u32_opts = NULL; + const struct wled_u32_opts wled3_opts[] = { { - "qcom,current-boost-limit", - &cfg->boost_i_limit, + .name = "qcom,current-boost-limit", + .val_ptr = &cfg->boost_i_limit, .cfg = &wled3_boost_i_limit_cfg, }, { - "qcom,current-limit", - &cfg->string_i_limit, + .name = "qcom,current-limit", + .val_ptr = &cfg->string_i_limit, .cfg = &wled3_string_i_limit_cfg, }, { - "qcom,ovp", - &cfg->ovp, + .name = "qcom,ovp", + .val_ptr = &cfg->ovp, .cfg = &wled3_ovp_cfg, }, { - "qcom,switching-freq", - &cfg->switch_freq, + .name = "qcom,switching-freq", + .val_ptr = &cfg->switch_freq, .cfg = &wled3_switch_freq_cfg, }, { - "qcom,num-strings", - &cfg->num_strings, + .name = "qcom,num-strings", + .val_ptr = &cfg->num_strings, .cfg = &wled3_num_strings_cfg, }, }; - const struct { - const char *name; - bool *val_ptr; - } bool_opts[] = { + + const struct wled_bool_opts bool_opts[] = { { "qcom,cs-out", &cfg->cs_out_en, }, { "qcom,ext-gen", &cfg->ext_gen, }, - { "qcom,cabc", &cfg->cabc_en, }, + { "qcom,cabc", &cfg->cabc, }, }; - rc = of_property_read_u32(dev->of_node, "reg", &val); - if (rc || val > 0xffff) { - dev_err(dev, "invalid IO resources\n"); - return rc ? rc : -EINVAL; + prop_addr = of_get_address(dev->of_node, 0, NULL, NULL); + if (!prop_addr) { + dev_err(wled->dev, "invalid IO resources\n"); + return -EINVAL; } - wled->addr = val; + wled->ctrl_addr = be32_to_cpu(*prop_addr); rc = of_property_read_string(dev->of_node, "label", &wled->name); if (rc) wled->name = devm_kasprintf(dev, GFP_KERNEL, "%pOFn", dev->of_node); - *cfg = wled3_config_defaults; - for (i = 0; i < ARRAY_SIZE(u32_opts); ++i) { + switch (version) { + case 3: + u32_opts = wled3_opts; + size = ARRAY_SIZE(wled3_opts); + *cfg = wled3_config_defaults; + wled->wled_set_brightness = wled3_set_brightness; + wled->max_string_count = 3; + break; + + default: + dev_err(wled->dev, "Invalid WLED version\n"); + return -EINVAL; + } + + for (i = 0; i < size; ++i) { rc = of_property_read_u32(dev->of_node, u32_opts[i].name, &val); if (rc == -EINVAL) { continue; @@ -338,12 +403,15 @@ static int wled_configure(struct wled *wled, struct device *dev) c = UINT_MAX; for (j = 0; c != val; j++) { - c = wled3_values(u32_opts[i].cfg, j); + c = wled_values(u32_opts[i].cfg, j); if (c == UINT_MAX) { dev_err(dev, "invalid value for '%s'\n", u32_opts[i].name); return -EINVAL; } + + if (c == val) + break; } dev_dbg(dev, "'%s' = %u\n", u32_opts[i].name, c); @@ -357,6 +425,15 @@ static int wled_configure(struct wled *wled, struct device *dev) cfg->num_strings = cfg->num_strings + 1; + string_len = of_property_count_elems_of_size(dev->of_node, + "qcom,enabled-strings", + sizeof(u32)); + if (string_len > 0) + of_property_read_u32_array(dev->of_node, + "qcom,enabled-strings", + wled->cfg.enabled_strings, + sizeof(u32)); + return 0; } @@ -370,6 +447,7 @@ static int wled_probe(struct platform_device *pdev) struct backlight_device *bl; struct wled *wled; struct regmap *regmap; + int version; u32 val; int rc; @@ -384,15 +462,32 @@ static int wled_probe(struct platform_device *pdev) return -ENOMEM; wled->regmap = regmap; + wled->dev = &pdev->dev; - rc = wled_configure(wled, &pdev->dev); - if (rc) - return rc; + version = (uintptr_t)of_device_get_match_data(&pdev->dev); + if (!version) { + dev_err(&pdev->dev, "Unknown device version\n"); + return -ENODEV; + } - rc = wled_setup(wled); + rc = wled_configure(wled, version); if (rc) return rc; + switch (version) { + case 3: + rc = wled3_setup(wled); + if (rc) { + dev_err(&pdev->dev, "wled3_setup failed\n"); + return rc; + } + break; + + default: + dev_err(wled->dev, "Invalid WLED version\n"); + break; + } + val = WLED_DEFAULT_BRIGHTNESS; of_property_read_u32(pdev->dev.of_node, "default-brightness", &val); @@ -407,7 +502,7 @@ static int wled_probe(struct platform_device *pdev) }; static const struct of_device_id wled_match_table[] = { - { .compatible = "qcom,pm8941-wled" }, + { .compatible = "qcom,pm8941-wled", .data = (void *)3 }, {} }; 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:01 +0000 Subject: [PATCH V10 5/8] backlight: qcom-wled: Restructure the driver for WLED3. Message-Id: <1572589624-6095-6-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 Restructure the driver to add the support for new WLED peripherals. Signed-off-by: Kiran Gunda Acked-by: Daniel Thompson --- drivers/video/backlight/qcom-wled.c | 373 ++++++++++++++++++++++-------------- 1 file changed, 234 insertions(+), 139 deletions(-) diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c index f191242..45eeda4 100644 --- a/drivers/video/backlight/qcom-wled.c +++ b/drivers/video/backlight/qcom-wled.c @@ -7,59 +7,71 @@ #include #include #include +#include #include /* From DT binding */ +#define WLED_MAX_STRINGS 4 + #define WLED_DEFAULT_BRIGHTNESS 2048 #define WLED3_SINK_REG_BRIGHT_MAX 0xFFF -#define WLED3_CTRL_REG_VAL_BASE 0x40 /* WLED3 control registers */ #define WLED3_CTRL_REG_MOD_EN 0x46 -#define WLED3_CTRL_REG_MOD_EN_BIT BIT(7) #define WLED3_CTRL_REG_MOD_EN_MASK BIT(7) +#define WLED3_CTRL_REG_MOD_EN_SHIFT 7 #define WLED3_CTRL_REG_FREQ 0x4c -#define WLED3_CTRL_REG_FREQ_MASK 0x0f +#define WLED3_CTRL_REG_FREQ_MASK GENMASK(3, 0) #define WLED3_CTRL_REG_OVP 0x4d -#define WLED3_CTRL_REG_OVP_MASK 0x03 +#define WLED3_CTRL_REG_OVP_MASK GENMASK(1, 0) #define WLED3_CTRL_REG_ILIMIT 0x4e -#define WLED3_CTRL_REG_ILIMIT_MASK 0x07 +#define WLED3_CTRL_REG_ILIMIT_MASK GENMASK(2, 0) /* WLED3 sink registers */ #define WLED3_SINK_REG_SYNC 0x47 -#define WLED3_SINK_REG_SYNC_MASK 0x07 -#define WLED3_SINK_REG_SYNC_LED1 BIT(0) -#define WLED3_SINK_REG_SYNC_LED2 BIT(1) -#define WLED3_SINK_REG_SYNC_LED3 BIT(2) -#define WLED3_SINK_REG_SYNC_ALL 0x07 #define WLED3_SINK_REG_SYNC_CLEAR 0x00 #define WLED3_SINK_REG_CURR_SINK 0x4f -#define WLED3_SINK_REG_CURR_SINK_MASK 0xe0 -#define WLED3_SINK_REG_CURR_SINK_SHFT 0x05 +#define WLED3_SINK_REG_CURR_SINK_MASK GENMASK(7, 5) +#define WLED3_SINK_REG_CURR_SINK_SHFT 5 -/* WLED3 per-'string' registers below */ -#define WLED3_SINK_REG_STR_OFFSET 0x10 +/* WLED3 specific per-'string' registers below */ +#define WLED3_SINK_REG_BRIGHT(n) (0x40 + n) -#define WLED3_SINK_REG_STR_MOD_EN_BASE 0x60 +#define WLED3_SINK_REG_STR_MOD_EN(n) (0x60 + (n * 0x10)) #define WLED3_SINK_REG_STR_MOD_MASK BIT(7) -#define WLED3_SINK_REG_STR_MOD_EN BIT(7) -#define WLED3_SINK_REG_STR_FULL_SCALE_CURR 0x62 -#define WLED3_SINK_REG_STR_FULL_SCALE_CURR_MASK 0x1f +#define WLED3_SINK_REG_STR_FULL_SCALE_CURR(n) (0x62 + (n * 0x10)) +#define WLED3_SINK_REG_STR_FULL_SCALE_CURR_MASK GENMASK(4, 0) -#define WLED3_SINK_REG_STR_MOD_SRC_BASE 0x63 -#define WLED3_SINK_REG_STR_MOD_SRC_MASK 0x01 +#define WLED3_SINK_REG_STR_MOD_SRC(n) (0x63 + (n * 0x10)) +#define WLED3_SINK_REG_STR_MOD_SRC_MASK BIT(0) #define WLED3_SINK_REG_STR_MOD_SRC_INT 0x00 #define WLED3_SINK_REG_STR_MOD_SRC_EXT 0x01 -#define WLED3_SINK_REG_STR_CABC_BASE 0x66 +#define WLED3_SINK_REG_STR_CABC(n) (0x66 + (n * 0x10)) #define WLED3_SINK_REG_STR_CABC_MASK BIT(7) -#define WLED3_SINK_REG_STR_CABC_EN BIT(7) + +struct wled_var_cfg { + const u32 *values; + u32 (*fn)(u32); + int size; +}; + +struct wled_u32_opts { + const char *name; + u32 *val_ptr; + const struct wled_var_cfg *cfg; +}; + +struct wled_bool_opts { + const char *name; + bool *val_ptr; +}; struct wled_config { u32 boost_i_limit; @@ -67,132 +79,179 @@ struct wled_config { u32 switch_freq; u32 num_strings; u32 string_i_limit; + u32 enabled_strings[WLED_MAX_STRINGS]; bool cs_out_en; bool ext_gen; - bool cabc_en; + bool cabc; }; struct wled { const char *name; + struct device *dev; struct regmap *regmap; - u16 addr; + u16 ctrl_addr; + u16 max_string_count; + u32 brightness; + u32 max_brightness; struct wled_config cfg; + int (*wled_set_brightness)(struct wled *wled, u16 brightness); }; +static int wled3_set_brightness(struct wled *wled, u16 brightness) +{ + int rc, i; + u8 v[2]; + + 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->ctrl_addr + + WLED3_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; + + rc = regmap_update_bits(wled->regmap, wled->ctrl_addr + + WLED3_CTRL_REG_MOD_EN, + WLED3_CTRL_REG_MOD_EN_MASK, + val << WLED3_CTRL_REG_MOD_EN_SHIFT); + return rc; +} + +static int wled_sync_toggle(struct wled *wled) +{ + int rc; + unsigned int mask = GENMASK(wled->max_string_count - 1, 0); + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_SINK_REG_SYNC, + mask, mask); + if (rc < 0) + return rc; + + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_SINK_REG_SYNC, + mask, WLED3_SINK_REG_SYNC_CLEAR); + + return rc; +} + static int wled_update_status(struct backlight_device *bl) { struct wled *wled = bl_get_data(bl); - u16 val = bl->props.brightness; - u8 ctrl = 0; - int rc; - int i; + u16 brightness = bl->props.brightness; + int rc = 0; if (bl->props.power != FB_BLANK_UNBLANK || bl->props.fb_blank != FB_BLANK_UNBLANK || bl->props.state & BL_CORE_FBBLANK) - val = 0; - - if (val != 0) - ctrl = WLED3_CTRL_REG_MOD_EN_BIT; + brightness = 0; - rc = regmap_update_bits(wled->regmap, - wled->addr + WLED3_CTRL_REG_MOD_EN, - WLED3_CTRL_REG_MOD_EN_MASK, ctrl); - if (rc) - return rc; + if (brightness) { + rc = wled->wled_set_brightness(wled, brightness); + if (rc < 0) { + dev_err(wled->dev, "wled failed to set brightness rc:%d\n", + rc); + return rc; + } - for (i = 0; i < wled->cfg.num_strings; ++i) { - u8 v[2] = { val & 0xff, (val >> 8) & 0xf }; + rc = wled_sync_toggle(wled); + if (rc < 0) { + dev_err(wled->dev, "wled sync failed rc:%d\n", rc); + return rc; + } + } - rc = regmap_bulk_write(wled->regmap, - wled->addr + WLED3_CTRL_REG_VAL_BASE + 2 * i, - v, 2); - if (rc) + if (!!brightness != !!wled->brightness) { + rc = wled_module_enable(wled, !!brightness); + if (rc < 0) { + dev_err(wled->dev, "wled enable failed rc:%d\n", rc); return rc; + } } - rc = regmap_update_bits(wled->regmap, - wled->addr + WLED3_SINK_REG_SYNC, - WLED3_SINK_REG_SYNC_MASK, WLED3_SINK_REG_SYNC_ALL); - if (rc) - return rc; + wled->brightness = brightness; - rc = regmap_update_bits(wled->regmap, - wled->addr + WLED3_SINK_REG_SYNC, - WLED3_SINK_REG_SYNC_MASK, WLED3_SINK_REG_SYNC_CLEAR); return rc; } -static int wled_setup(struct wled *wled) +static int wled3_setup(struct wled *wled) { - int rc; - int i; + u16 addr; + u8 sink_en = 0; + int rc, i, j; rc = regmap_update_bits(wled->regmap, - wled->addr + WLED3_CTRL_REG_OVP, - WLED3_CTRL_REG_OVP_MASK, wled->cfg.ovp); + wled->ctrl_addr + WLED3_CTRL_REG_OVP, + WLED3_CTRL_REG_OVP_MASK, wled->cfg.ovp); if (rc) return rc; rc = regmap_update_bits(wled->regmap, - wled->addr + WLED3_CTRL_REG_ILIMIT, - WLED3_CTRL_REG_ILIMIT_MASK, wled->cfg.boost_i_limit); + wled->ctrl_addr + WLED3_CTRL_REG_ILIMIT, + WLED3_CTRL_REG_ILIMIT_MASK, + wled->cfg.boost_i_limit); if (rc) return rc; rc = regmap_update_bits(wled->regmap, - wled->addr + WLED3_CTRL_REG_FREQ, - WLED3_CTRL_REG_FREQ_MASK, wled->cfg.switch_freq); + wled->ctrl_addr + WLED3_CTRL_REG_FREQ, + WLED3_CTRL_REG_FREQ_MASK, + wled->cfg.switch_freq); if (rc) return rc; - if (wled->cfg.cs_out_en) { - u8 all = (BIT(wled->cfg.num_strings) - 1) - << WLED3_SINK_REG_CURR_SINK_SHFT; - - rc = regmap_update_bits(wled->regmap, - wled->addr + WLED3_SINK_REG_CURR_SINK, - WLED3_SINK_REG_CURR_SINK_MASK, all); - if (rc) - return rc; - } - for (i = 0; i < wled->cfg.num_strings; ++i) { - u16 addr = wled->addr + WLED3_SINK_REG_STR_OFFSET * i; - - rc = regmap_update_bits(wled->regmap, - addr + WLED3_SINK_REG_STR_MOD_EN_BASE, - WLED3_SINK_REG_STR_MOD_MASK, - WLED3_SINK_REG_STR_MOD_EN); + j = wled->cfg.enabled_strings[i]; + addr = wled->ctrl_addr + WLED3_SINK_REG_STR_MOD_EN(j); + rc = regmap_update_bits(wled->regmap, addr, + WLED3_SINK_REG_STR_MOD_MASK, + WLED3_SINK_REG_STR_MOD_MASK); if (rc) return rc; if (wled->cfg.ext_gen) { - rc = regmap_update_bits(wled->regmap, - addr + WLED3_SINK_REG_STR_MOD_SRC_BASE, - WLED3_SINK_REG_STR_MOD_SRC_MASK, - WLED3_SINK_REG_STR_MOD_SRC_EXT); + addr = wled->ctrl_addr + WLED3_SINK_REG_STR_MOD_SRC(j); + rc = regmap_update_bits(wled->regmap, addr, + WLED3_SINK_REG_STR_MOD_SRC_MASK, + WLED3_SINK_REG_STR_MOD_SRC_EXT); if (rc) return rc; } - rc = regmap_update_bits(wled->regmap, - addr + WLED3_SINK_REG_STR_FULL_SCALE_CURR, - WLED3_SINK_REG_STR_FULL_SCALE_CURR_MASK, - wled->cfg.string_i_limit); + addr = wled->ctrl_addr + WLED3_SINK_REG_STR_FULL_SCALE_CURR(j); + rc = regmap_update_bits(wled->regmap, addr, + WLED3_SINK_REG_STR_FULL_SCALE_CURR_MASK, + wled->cfg.string_i_limit); if (rc) return rc; - rc = regmap_update_bits(wled->regmap, - addr + WLED3_SINK_REG_STR_CABC_BASE, - WLED3_SINK_REG_STR_CABC_MASK, - wled->cfg.cabc_en ? - WLED3_SINK_REG_STR_CABC_EN : 0); + addr = wled->ctrl_addr + WLED3_SINK_REG_STR_CABC(j); + rc = regmap_update_bits(wled->regmap, addr, + WLED3_SINK_REG_STR_CABC_MASK, + wled->cfg.cabc ? + WLED3_SINK_REG_STR_CABC_MASK : 0); if (rc) return rc; + + sink_en |= BIT(j + WLED3_SINK_REG_CURR_SINK_SHFT); } + rc = regmap_update_bits(wled->regmap, + wled->ctrl_addr + WLED3_SINK_REG_CURR_SINK, + WLED3_SINK_REG_CURR_SINK_MASK, sink_en); + if (rc) + return rc; + return 0; } @@ -200,17 +259,12 @@ static int wled_setup(struct wled *wled) .boost_i_limit = 3, .string_i_limit = 20, .ovp = 2, + .num_strings = 3, .switch_freq = 5, - .num_strings = 0, .cs_out_en = false, .ext_gen = false, - .cabc_en = false, -}; - -struct wled_var_cfg { - const u32 *values; - u32 (*fn)(u32); - int size; + .cabc = false, + .enabled_strings = {0, 1, 2, 3}, }; static const u32 wled3_boost_i_limit_values[] = { @@ -255,7 +309,11 @@ static u32 wled3_switch_freq_values_fn(u32 idx) .size = 26, }; -static u32 wled3_values(const struct wled_var_cfg *cfg, u32 idx) +static const struct wled_var_cfg wled3_string_cfg = { + .size = 8, +}; + +static u32 wled_values(const struct wled_var_cfg *cfg, u32 idx) { if (idx >= cfg->size) return UINT_MAX; @@ -266,68 +324,75 @@ static u32 wled3_values(const struct wled_var_cfg *cfg, u32 idx) return idx; } -static int wled_configure(struct wled *wled, struct device *dev) +static int wled_configure(struct wled *wled, int version) { struct wled_config *cfg = &wled->cfg; - u32 val; - int rc; - u32 c; - int i; - int j; - - const struct { - const char *name; - u32 *val_ptr; - const struct wled_var_cfg *cfg; - } u32_opts[] = { + struct device *dev = wled->dev; + const __be32 *prop_addr; + u32 size, val, c, string_len; + int rc, i, j; + + const struct wled_u32_opts *u32_opts = NULL; + const struct wled_u32_opts wled3_opts[] = { { - "qcom,current-boost-limit", - &cfg->boost_i_limit, + .name = "qcom,current-boost-limit", + .val_ptr = &cfg->boost_i_limit, .cfg = &wled3_boost_i_limit_cfg, }, { - "qcom,current-limit", - &cfg->string_i_limit, + .name = "qcom,current-limit", + .val_ptr = &cfg->string_i_limit, .cfg = &wled3_string_i_limit_cfg, }, { - "qcom,ovp", - &cfg->ovp, + .name = "qcom,ovp", + .val_ptr = &cfg->ovp, .cfg = &wled3_ovp_cfg, }, { - "qcom,switching-freq", - &cfg->switch_freq, + .name = "qcom,switching-freq", + .val_ptr = &cfg->switch_freq, .cfg = &wled3_switch_freq_cfg, }, { - "qcom,num-strings", - &cfg->num_strings, + .name = "qcom,num-strings", + .val_ptr = &cfg->num_strings, .cfg = &wled3_num_strings_cfg, }, }; - const struct { - const char *name; - bool *val_ptr; - } bool_opts[] = { + + const struct wled_bool_opts bool_opts[] = { { "qcom,cs-out", &cfg->cs_out_en, }, { "qcom,ext-gen", &cfg->ext_gen, }, - { "qcom,cabc", &cfg->cabc_en, }, + { "qcom,cabc", &cfg->cabc, }, }; - rc = of_property_read_u32(dev->of_node, "reg", &val); - if (rc || val > 0xffff) { - dev_err(dev, "invalid IO resources\n"); - return rc ? rc : -EINVAL; + prop_addr = of_get_address(dev->of_node, 0, NULL, NULL); + if (!prop_addr) { + dev_err(wled->dev, "invalid IO resources\n"); + return -EINVAL; } - wled->addr = val; + wled->ctrl_addr = be32_to_cpu(*prop_addr); rc = of_property_read_string(dev->of_node, "label", &wled->name); if (rc) wled->name = devm_kasprintf(dev, GFP_KERNEL, "%pOFn", dev->of_node); - *cfg = wled3_config_defaults; - for (i = 0; i < ARRAY_SIZE(u32_opts); ++i) { + switch (version) { + case 3: + u32_opts = wled3_opts; + size = ARRAY_SIZE(wled3_opts); + *cfg = wled3_config_defaults; + wled->wled_set_brightness = wled3_set_brightness; + wled->max_string_count = 3; + break; + + default: + dev_err(wled->dev, "Invalid WLED version\n"); + return -EINVAL; + } + + for (i = 0; i < size; ++i) { rc = of_property_read_u32(dev->of_node, u32_opts[i].name, &val); if (rc = -EINVAL) { continue; @@ -338,12 +403,15 @@ static int wled_configure(struct wled *wled, struct device *dev) c = UINT_MAX; for (j = 0; c != val; j++) { - c = wled3_values(u32_opts[i].cfg, j); + c = wled_values(u32_opts[i].cfg, j); if (c = UINT_MAX) { dev_err(dev, "invalid value for '%s'\n", u32_opts[i].name); return -EINVAL; } + + if (c = val) + break; } dev_dbg(dev, "'%s' = %u\n", u32_opts[i].name, c); @@ -357,6 +425,15 @@ static int wled_configure(struct wled *wled, struct device *dev) cfg->num_strings = cfg->num_strings + 1; + string_len = of_property_count_elems_of_size(dev->of_node, + "qcom,enabled-strings", + sizeof(u32)); + if (string_len > 0) + of_property_read_u32_array(dev->of_node, + "qcom,enabled-strings", + wled->cfg.enabled_strings, + sizeof(u32)); + return 0; } @@ -370,6 +447,7 @@ static int wled_probe(struct platform_device *pdev) struct backlight_device *bl; struct wled *wled; struct regmap *regmap; + int version; u32 val; int rc; @@ -384,15 +462,32 @@ static int wled_probe(struct platform_device *pdev) return -ENOMEM; wled->regmap = regmap; + wled->dev = &pdev->dev; - rc = wled_configure(wled, &pdev->dev); - if (rc) - return rc; + version = (uintptr_t)of_device_get_match_data(&pdev->dev); + if (!version) { + dev_err(&pdev->dev, "Unknown device version\n"); + return -ENODEV; + } - rc = wled_setup(wled); + rc = wled_configure(wled, version); if (rc) return rc; + switch (version) { + case 3: + rc = wled3_setup(wled); + if (rc) { + dev_err(&pdev->dev, "wled3_setup failed\n"); + return rc; + } + break; + + default: + dev_err(wled->dev, "Invalid WLED version\n"); + break; + } + val = WLED_DEFAULT_BRIGHTNESS; of_property_read_u32(pdev->dev.of_node, "default-brightness", &val); @@ -407,7 +502,7 @@ static int wled_probe(struct platform_device *pdev) }; static const struct of_device_id wled_match_table[] = { - { .compatible = "qcom,pm8941-wled" }, + { .compatible = "qcom,pm8941-wled", .data = (void *)3 }, {} }; 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 BD954CA9ECE for ; Fri, 1 Nov 2019 08:10:25 +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 99055208E3 for ; Fri, 1 Nov 2019 08:10:25 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 99055208E3 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 1D3406F765; Fri, 1 Nov 2019 08:09:58 +0000 (UTC) Received: from smtp.codeaurora.org (smtp.codeaurora.org [198.145.29.96]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7E5CB6F6FF for ; Fri, 1 Nov 2019 06:28:09 +0000 (UTC) Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 559A360EE4; Fri, 1 Nov 2019 06:28:08 +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 AB02F60DE9; Fri, 1 Nov 2019 06:27:58 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org AB02F60DE9 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 5/8] backlight: qcom-wled: Restructure the driver for WLED3. Date: Fri, 1 Nov 2019 11:57:01 +0530 Message-Id: <1572589624-6095-6-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=1572589689; bh=XDDayIt0SyW3eZnIq3LHOzJB47k4lBZqsbBwsxBkEA8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Vaw3+tcmYvlV6PQDJuQq3vdIebTa4foo+e9/fVoKJcHD90qkJ23SoJR6ccZFzythN Shx5GhmTQDAjoFZKFPq4AaEVmbZ+jiRO5SuewBSOqDvjO5hEoIQqEr3xualHQlrirq OAv1gM//KNOw683XJlbN2Bhi00kXCr9r+FUMhLdI= X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1572589685; bh=XDDayIt0SyW3eZnIq3LHOzJB47k4lBZqsbBwsxBkEA8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DjwIyBjR2t9/xdbjYNouEj3rPbwX6Lao78csW4ZBZA8vBhS4ik380k3KlD2mfNxGv fuA+auBz1RS5hP7AxGelJum3EBHkbbseIqmSNrk49iuhpBWlBH6s2LKeThsguoe5RE r7JIeRzpihT3ctldWnSyD5EaQOC2TA+KsEFxHVjs= 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: <20191101062701.6L_XJ-23AS0UkbcGlpogZDpnr-X5bvnFI8t7kEJSyy8@z> UmVzdHJ1Y3R1cmUgdGhlIGRyaXZlciB0byBhZGQgdGhlIHN1cHBvcnQgZm9yIG5ldyBXTEVECnBl cmlwaGVyYWxzLgoKU2lnbmVkLW9mZi1ieTogS2lyYW4gR3VuZGEgPGtndW5kYUBjb2RlYXVyb3Jh Lm9yZz4KQWNrZWQtYnk6IERhbmllbCBUaG9tcHNvbiA8ZGFuaWVsLnRob21wc29uQGxpbmFyby5v cmc+Ci0tLQogZHJpdmVycy92aWRlby9iYWNrbGlnaHQvcWNvbS13bGVkLmMgfCAzNzMgKysrKysr KysrKysrKysrKysrKysrKy0tLS0tLS0tLS0tLS0tCiAxIGZpbGUgY2hhbmdlZCwgMjM0IGluc2Vy dGlvbnMoKyksIDEzOSBkZWxldGlvbnMoLSkKCmRpZmYgLS1naXQgYS9kcml2ZXJzL3ZpZGVvL2Jh Y2tsaWdodC9xY29tLXdsZWQuYyBiL2RyaXZlcnMvdmlkZW8vYmFja2xpZ2h0L3Fjb20td2xlZC5j CmluZGV4IGYxOTEyNDIuLjQ1ZWVkYTQgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvdmlkZW8vYmFja2xp Z2h0L3Fjb20td2xlZC5jCisrKyBiL2RyaXZlcnMvdmlkZW8vYmFja2xpZ2h0L3Fjb20td2xlZC5j CkBAIC03LDU5ICs3LDcxIEBACiAjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CiAjaW5jbHVkZSA8 bGludXgvb2YuaD4KICNpbmNsdWRlIDxsaW51eC9vZl9kZXZpY2UuaD4KKyNpbmNsdWRlIDxsaW51 eC9vZl9hZGRyZXNzLmg+CiAjaW5jbHVkZSA8bGludXgvcmVnbWFwLmg+CiAKIC8qIEZyb20gRFQg YmluZGluZyAqLworI2RlZmluZSBXTEVEX01BWF9TVFJJTkdTCQkJCTQKKwogI2RlZmluZSBXTEVE X0RFRkFVTFRfQlJJR0hUTkVTUwkJCQkyMDQ4CiAKICNkZWZpbmUgV0xFRDNfU0lOS19SRUdfQlJJ R0hUX01BWAkJCTB4RkZGCi0jZGVmaW5lIFdMRUQzX0NUUkxfUkVHX1ZBTF9CQVNFCQkJCTB4NDAK IAogLyogV0xFRDMgY29udHJvbCByZWdpc3RlcnMgKi8KICNkZWZpbmUgV0xFRDNfQ1RSTF9SRUdf TU9EX0VOCQkJCTB4NDYKLSNkZWZpbmUgIFdMRUQzX0NUUkxfUkVHX01PRF9FTl9CSVQJCQlCSVQo NykKICNkZWZpbmUgIFdMRUQzX0NUUkxfUkVHX01PRF9FTl9NQVNLCQkJQklUKDcpCisjZGVmaW5l ICBXTEVEM19DVFJMX1JFR19NT0RfRU5fU0hJRlQJCQk3CiAKICNkZWZpbmUgV0xFRDNfQ1RSTF9S RUdfRlJFUQkJCQkweDRjCi0jZGVmaW5lICBXTEVEM19DVFJMX1JFR19GUkVRX01BU0sJCQkweDBm CisjZGVmaW5lICBXTEVEM19DVFJMX1JFR19GUkVRX01BU0sJCQlHRU5NQVNLKDMsIDApCiAKICNk ZWZpbmUgV0xFRDNfQ1RSTF9SRUdfT1ZQCQkJCTB4NGQKLSNkZWZpbmUgIFdMRUQzX0NUUkxfUkVH X09WUF9NQVNLCQkJMHgwMworI2RlZmluZSAgV0xFRDNfQ1RSTF9SRUdfT1ZQX01BU0sJCQkJR0VO TUFTSygxLCAwKQogCiAjZGVmaW5lIFdMRUQzX0NUUkxfUkVHX0lMSU1JVAkJCQkweDRlCi0jZGVm aW5lICBXTEVEM19DVFJMX1JFR19JTElNSVRfTUFTSwkJCTB4MDcKKyNkZWZpbmUgIFdMRUQzX0NU UkxfUkVHX0lMSU1JVF9NQVNLCQkJR0VOTUFTSygyLCAwKQogCiAvKiBXTEVEMyBzaW5rIHJlZ2lz dGVycyAqLwogI2RlZmluZSBXTEVEM19TSU5LX1JFR19TWU5DCQkJCTB4NDcKLSNkZWZpbmUgIFdM RUQzX1NJTktfUkVHX1NZTkNfTUFTSwkJCTB4MDcKLSNkZWZpbmUgIFdMRUQzX1NJTktfUkVHX1NZ TkNfTEVEMQkJCUJJVCgwKQotI2RlZmluZSAgV0xFRDNfU0lOS19SRUdfU1lOQ19MRUQyCQkJQklU KDEpCi0jZGVmaW5lICBXTEVEM19TSU5LX1JFR19TWU5DX0xFRDMJCQlCSVQoMikKLSNkZWZpbmUg IFdMRUQzX1NJTktfUkVHX1NZTkNfQUxMCQkJMHgwNwogI2RlZmluZSAgV0xFRDNfU0lOS19SRUdf U1lOQ19DTEVBUgkJCTB4MDAKIAogI2RlZmluZSBXTEVEM19TSU5LX1JFR19DVVJSX1NJTksJCQkw eDRmCi0jZGVmaW5lICBXTEVEM19TSU5LX1JFR19DVVJSX1NJTktfTUFTSwkJCTB4ZTAKLSNkZWZp bmUgIFdMRUQzX1NJTktfUkVHX0NVUlJfU0lOS19TSEZUCQkJMHgwNQorI2RlZmluZSAgV0xFRDNf U0lOS19SRUdfQ1VSUl9TSU5LX01BU0sJCQlHRU5NQVNLKDcsIDUpCisjZGVmaW5lICBXTEVEM19T SU5LX1JFR19DVVJSX1NJTktfU0hGVAkJCTUKIAotLyogV0xFRDMgcGVyLSdzdHJpbmcnIHJlZ2lz dGVycyBiZWxvdyAqLwotI2RlZmluZSBXTEVEM19TSU5LX1JFR19TVFJfT0ZGU0VUCQkJMHgxMAor LyogV0xFRDMgc3BlY2lmaWMgcGVyLSdzdHJpbmcnIHJlZ2lzdGVycyBiZWxvdyAqLworI2RlZmlu ZSBXTEVEM19TSU5LX1JFR19CUklHSFQobikJCQkoMHg0MCArIG4pCiAKLSNkZWZpbmUgV0xFRDNf U0lOS19SRUdfU1RSX01PRF9FTl9CQVNFCQkJMHg2MAorI2RlZmluZSBXTEVEM19TSU5LX1JFR19T VFJfTU9EX0VOKG4pCQkJKDB4NjAgKyAobiAqIDB4MTApKQogI2RlZmluZSAgV0xFRDNfU0lOS19S RUdfU1RSX01PRF9NQVNLCQkJQklUKDcpCi0jZGVmaW5lICBXTEVEM19TSU5LX1JFR19TVFJfTU9E X0VOCQkJQklUKDcpCiAKLSNkZWZpbmUgV0xFRDNfU0lOS19SRUdfU1RSX0ZVTExfU0NBTEVfQ1VS UgkJMHg2MgotI2RlZmluZSAgV0xFRDNfU0lOS19SRUdfU1RSX0ZVTExfU0NBTEVfQ1VSUl9NQVNL CTB4MWYKKyNkZWZpbmUgV0xFRDNfU0lOS19SRUdfU1RSX0ZVTExfU0NBTEVfQ1VSUihuKQkJKDB4 NjIgKyAobiAqIDB4MTApKQorI2RlZmluZSAgV0xFRDNfU0lOS19SRUdfU1RSX0ZVTExfU0NBTEVf Q1VSUl9NQVNLCUdFTk1BU0soNCwgMCkKIAotI2RlZmluZSBXTEVEM19TSU5LX1JFR19TVFJfTU9E X1NSQ19CQVNFCQkJMHg2MwotI2RlZmluZSAgV0xFRDNfU0lOS19SRUdfU1RSX01PRF9TUkNfTUFT SwkJMHgwMQorI2RlZmluZSBXTEVEM19TSU5LX1JFR19TVFJfTU9EX1NSQyhuKQkJCSgweDYzICsg KG4gKiAweDEwKSkKKyNkZWZpbmUgIFdMRUQzX1NJTktfUkVHX1NUUl9NT0RfU1JDX01BU0sJCUJJ VCgwKQogI2RlZmluZSAgV0xFRDNfU0lOS19SRUdfU1RSX01PRF9TUkNfSU5UCQkJMHgwMAogI2Rl ZmluZSAgV0xFRDNfU0lOS19SRUdfU1RSX01PRF9TUkNfRVhUCQkJMHgwMQogCi0jZGVmaW5lIFdM RUQzX1NJTktfUkVHX1NUUl9DQUJDX0JBU0UJCQkweDY2CisjZGVmaW5lIFdMRUQzX1NJTktfUkVH X1NUUl9DQUJDKG4pCQkJKDB4NjYgKyAobiAqIDB4MTApKQogI2RlZmluZSAgV0xFRDNfU0lOS19S RUdfU1RSX0NBQkNfTUFTSwkJCUJJVCg3KQotI2RlZmluZSAgV0xFRDNfU0lOS19SRUdfU1RSX0NB QkNfRU4JCQlCSVQoNykKKworc3RydWN0IHdsZWRfdmFyX2NmZyB7CisJY29uc3QgdTMyICp2YWx1 ZXM7CisJdTMyICgqZm4pKHUzMik7CisJaW50IHNpemU7Cit9OworCitzdHJ1Y3Qgd2xlZF91MzJf b3B0cyB7CisJY29uc3QgY2hhciAqbmFtZTsKKwl1MzIgKnZhbF9wdHI7CisJY29uc3Qgc3RydWN0 IHdsZWRfdmFyX2NmZyAqY2ZnOworfTsKKworc3RydWN0IHdsZWRfYm9vbF9vcHRzIHsKKwljb25z dCBjaGFyICpuYW1lOworCWJvb2wgKnZhbF9wdHI7Cit9OwogCiBzdHJ1Y3Qgd2xlZF9jb25maWcg ewogCXUzMiBib29zdF9pX2xpbWl0OwpAQCAtNjcsMTMyICs3OSwxNzkgQEAgc3RydWN0IHdsZWRf Y29uZmlnIHsKIAl1MzIgc3dpdGNoX2ZyZXE7CiAJdTMyIG51bV9zdHJpbmdzOwogCXUzMiBzdHJp bmdfaV9saW1pdDsKKwl1MzIgZW5hYmxlZF9zdHJpbmdzW1dMRURfTUFYX1NUUklOR1NdOwogCWJv b2wgY3Nfb3V0X2VuOwogCWJvb2wgZXh0X2dlbjsKLQlib29sIGNhYmNfZW47CisJYm9vbCBjYWJj OwogfTsKIAogc3RydWN0IHdsZWQgewogCWNvbnN0IGNoYXIgKm5hbWU7CisJc3RydWN0IGRldmlj ZSAqZGV2OwogCXN0cnVjdCByZWdtYXAgKnJlZ21hcDsKLQl1MTYgYWRkcjsKKwl1MTYgY3RybF9h ZGRyOworCXUxNiBtYXhfc3RyaW5nX2NvdW50OworCXUzMiBicmlnaHRuZXNzOworCXUzMiBtYXhf YnJpZ2h0bmVzczsKIAogCXN0cnVjdCB3bGVkX2NvbmZpZyBjZmc7CisJaW50ICgqd2xlZF9zZXRf YnJpZ2h0bmVzcykoc3RydWN0IHdsZWQgKndsZWQsIHUxNiBicmlnaHRuZXNzKTsKIH07CiAKK3N0 YXRpYyBpbnQgd2xlZDNfc2V0X2JyaWdodG5lc3Moc3RydWN0IHdsZWQgKndsZWQsIHUxNiBicmln aHRuZXNzKQoreworCWludCByYywgaTsKKwl1OCB2WzJdOworCisJdlswXSA9IGJyaWdodG5lc3Mg JiAweGZmOworCXZbMV0gPSAoYnJpZ2h0bmVzcyA+PiA4KSAmIDB4ZjsKKworCWZvciAoaSA9IDA7 ICBpIDwgd2xlZC0+Y2ZnLm51bV9zdHJpbmdzOyArK2kpIHsKKwkJcmMgPSByZWdtYXBfYnVsa193 cml0ZSh3bGVkLT5yZWdtYXAsIHdsZWQtPmN0cmxfYWRkciArCisJCQkJICAgICAgIFdMRUQzX1NJ TktfUkVHX0JSSUdIVChpKSwgdiwgMik7CisJCWlmIChyYyA8IDApCisJCQlyZXR1cm4gcmM7CisJ fQorCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgd2xlZF9tb2R1bGVfZW5hYmxlKHN0cnVj dCB3bGVkICp3bGVkLCBpbnQgdmFsKQoreworCWludCByYzsKKworCXJjID0gcmVnbWFwX3VwZGF0 ZV9iaXRzKHdsZWQtPnJlZ21hcCwgd2xlZC0+Y3RybF9hZGRyICsKKwkJCQlXTEVEM19DVFJMX1JF R19NT0RfRU4sCisJCQkJV0xFRDNfQ1RSTF9SRUdfTU9EX0VOX01BU0ssCisJCQkJdmFsIDw8IFdM RUQzX0NUUkxfUkVHX01PRF9FTl9TSElGVCk7CisJcmV0dXJuIHJjOworfQorCitzdGF0aWMgaW50 IHdsZWRfc3luY190b2dnbGUoc3RydWN0IHdsZWQgKndsZWQpCit7CisJaW50IHJjOworCXVuc2ln bmVkIGludCBtYXNrID0gR0VOTUFTSyh3bGVkLT5tYXhfc3RyaW5nX2NvdW50IC0gMSwgMCk7CisK KwlyYyA9IHJlZ21hcF91cGRhdGVfYml0cyh3bGVkLT5yZWdtYXAsCisJCQkJd2xlZC0+Y3RybF9h ZGRyICsgV0xFRDNfU0lOS19SRUdfU1lOQywKKwkJCQltYXNrLCBtYXNrKTsKKwlpZiAocmMgPCAw KQorCQlyZXR1cm4gcmM7CisKKwlyYyA9IHJlZ21hcF91cGRhdGVfYml0cyh3bGVkLT5yZWdtYXAs CisJCQkJd2xlZC0+Y3RybF9hZGRyICsgV0xFRDNfU0lOS19SRUdfU1lOQywKKwkJCQltYXNrLCBX TEVEM19TSU5LX1JFR19TWU5DX0NMRUFSKTsKKworCXJldHVybiByYzsKK30KKwogc3RhdGljIGlu dCB3bGVkX3VwZGF0ZV9zdGF0dXMoc3RydWN0IGJhY2tsaWdodF9kZXZpY2UgKmJsKQogewogCXN0 cnVjdCB3bGVkICp3bGVkID0gYmxfZ2V0X2RhdGEoYmwpOwotCXUxNiB2YWwgPSBibC0+cHJvcHMu YnJpZ2h0bmVzczsKLQl1OCBjdHJsID0gMDsKLQlpbnQgcmM7Ci0JaW50IGk7CisJdTE2IGJyaWdo dG5lc3MgPSBibC0+cHJvcHMuYnJpZ2h0bmVzczsKKwlpbnQgcmMgPSAwOwogCiAJaWYgKGJsLT5w cm9wcy5wb3dlciAhPSBGQl9CTEFOS19VTkJMQU5LIHx8CiAJICAgIGJsLT5wcm9wcy5mYl9ibGFu ayAhPSBGQl9CTEFOS19VTkJMQU5LIHx8CiAJICAgIGJsLT5wcm9wcy5zdGF0ZSAmIEJMX0NPUkVf RkJCTEFOSykKLQkJdmFsID0gMDsKLQotCWlmICh2YWwgIT0gMCkKLQkJY3RybCA9IFdMRUQzX0NU UkxfUkVHX01PRF9FTl9CSVQ7CisJCWJyaWdodG5lc3MgPSAwOwogCi0JcmMgPSByZWdtYXBfdXBk YXRlX2JpdHMod2xlZC0+cmVnbWFwLAotCQkJd2xlZC0+YWRkciArIFdMRUQzX0NUUkxfUkVHX01P RF9FTiwKLQkJCVdMRUQzX0NUUkxfUkVHX01PRF9FTl9NQVNLLCBjdHJsKTsKLQlpZiAocmMpCi0J CXJldHVybiByYzsKKwlpZiAoYnJpZ2h0bmVzcykgeworCQlyYyA9IHdsZWQtPndsZWRfc2V0X2Jy aWdodG5lc3Mod2xlZCwgYnJpZ2h0bmVzcyk7CisJCWlmIChyYyA8IDApIHsKKwkJCWRldl9lcnIo d2xlZC0+ZGV2LCAid2xlZCBmYWlsZWQgdG8gc2V0IGJyaWdodG5lc3MgcmM6JWRcbiIsCisJCQkJ cmMpOworCQkJcmV0dXJuIHJjOworCQl9CiAKLQlmb3IgKGkgPSAwOyBpIDwgd2xlZC0+Y2ZnLm51 bV9zdHJpbmdzOyArK2kpIHsKLQkJdTggdlsyXSA9IHsgdmFsICYgMHhmZiwgKHZhbCA+PiA4KSAm IDB4ZiB9OworCQlyYyA9IHdsZWRfc3luY190b2dnbGUod2xlZCk7CisJCWlmIChyYyA8IDApIHsK KwkJCWRldl9lcnIod2xlZC0+ZGV2LCAid2xlZCBzeW5jIGZhaWxlZCByYzolZFxuIiwgcmMpOwor CQkJcmV0dXJuIHJjOworCQl9CisJfQogCi0JCXJjID0gcmVnbWFwX2J1bGtfd3JpdGUod2xlZC0+ cmVnbWFwLAotCQkJCXdsZWQtPmFkZHIgKyBXTEVEM19DVFJMX1JFR19WQUxfQkFTRSArIDIgKiBp LAotCQkJCXYsIDIpOwotCQlpZiAocmMpCisJaWYgKCEhYnJpZ2h0bmVzcyAhPSAhIXdsZWQtPmJy aWdodG5lc3MpIHsKKwkJcmMgPSB3bGVkX21vZHVsZV9lbmFibGUod2xlZCwgISFicmlnaHRuZXNz KTsKKwkJaWYgKHJjIDwgMCkgeworCQkJZGV2X2Vycih3bGVkLT5kZXYsICJ3bGVkIGVuYWJsZSBm YWlsZWQgcmM6JWRcbiIsIHJjKTsKIAkJCXJldHVybiByYzsKKwkJfQogCX0KIAotCXJjID0gcmVn bWFwX3VwZGF0ZV9iaXRzKHdsZWQtPnJlZ21hcCwKLQkJCXdsZWQtPmFkZHIgKyBXTEVEM19TSU5L X1JFR19TWU5DLAotCQkJV0xFRDNfU0lOS19SRUdfU1lOQ19NQVNLLCBXTEVEM19TSU5LX1JFR19T WU5DX0FMTCk7Ci0JaWYgKHJjKQotCQlyZXR1cm4gcmM7CisJd2xlZC0+YnJpZ2h0bmVzcyA9IGJy aWdodG5lc3M7CiAKLQlyYyA9IHJlZ21hcF91cGRhdGVfYml0cyh3bGVkLT5yZWdtYXAsCi0JCQl3 bGVkLT5hZGRyICsgV0xFRDNfU0lOS19SRUdfU1lOQywKLQkJCVdMRUQzX1NJTktfUkVHX1NZTkNf TUFTSywgV0xFRDNfU0lOS19SRUdfU1lOQ19DTEVBUik7CiAJcmV0dXJuIHJjOwogfQogCi1zdGF0 aWMgaW50IHdsZWRfc2V0dXAoc3RydWN0IHdsZWQgKndsZWQpCitzdGF0aWMgaW50IHdsZWQzX3Nl dHVwKHN0cnVjdCB3bGVkICp3bGVkKQogewotCWludCByYzsKLQlpbnQgaTsKKwl1MTYgYWRkcjsK Kwl1OCBzaW5rX2VuID0gMDsKKwlpbnQgcmMsIGksIGo7CiAKIAlyYyA9IHJlZ21hcF91cGRhdGVf Yml0cyh3bGVkLT5yZWdtYXAsCi0JCQl3bGVkLT5hZGRyICsgV0xFRDNfQ1RSTF9SRUdfT1ZQLAot CQkJV0xFRDNfQ1RSTF9SRUdfT1ZQX01BU0ssIHdsZWQtPmNmZy5vdnApOworCQkJCXdsZWQtPmN0 cmxfYWRkciArIFdMRUQzX0NUUkxfUkVHX09WUCwKKwkJCQlXTEVEM19DVFJMX1JFR19PVlBfTUFT Sywgd2xlZC0+Y2ZnLm92cCk7CiAJaWYgKHJjKQogCQlyZXR1cm4gcmM7CiAKIAlyYyA9IHJlZ21h cF91cGRhdGVfYml0cyh3bGVkLT5yZWdtYXAsCi0JCQl3bGVkLT5hZGRyICsgV0xFRDNfQ1RSTF9S RUdfSUxJTUlULAotCQkJV0xFRDNfQ1RSTF9SRUdfSUxJTUlUX01BU0ssIHdsZWQtPmNmZy5ib29z dF9pX2xpbWl0KTsKKwkJCQl3bGVkLT5jdHJsX2FkZHIgKyBXTEVEM19DVFJMX1JFR19JTElNSVQs CisJCQkJV0xFRDNfQ1RSTF9SRUdfSUxJTUlUX01BU0ssCisJCQkJd2xlZC0+Y2ZnLmJvb3N0X2lf bGltaXQpOwogCWlmIChyYykKIAkJcmV0dXJuIHJjOwogCiAJcmMgPSByZWdtYXBfdXBkYXRlX2Jp dHMod2xlZC0+cmVnbWFwLAotCQkJd2xlZC0+YWRkciArIFdMRUQzX0NUUkxfUkVHX0ZSRVEsCi0J CQlXTEVEM19DVFJMX1JFR19GUkVRX01BU0ssIHdsZWQtPmNmZy5zd2l0Y2hfZnJlcSk7CisJCQkJ d2xlZC0+Y3RybF9hZGRyICsgV0xFRDNfQ1RSTF9SRUdfRlJFUSwKKwkJCQlXTEVEM19DVFJMX1JF R19GUkVRX01BU0ssCisJCQkJd2xlZC0+Y2ZnLnN3aXRjaF9mcmVxKTsKIAlpZiAocmMpCiAJCXJl dHVybiByYzsKIAotCWlmICh3bGVkLT5jZmcuY3Nfb3V0X2VuKSB7Ci0JCXU4IGFsbCA9IChCSVQo d2xlZC0+Y2ZnLm51bV9zdHJpbmdzKSAtIDEpCi0JCQkJPDwgV0xFRDNfU0lOS19SRUdfQ1VSUl9T SU5LX1NIRlQ7Ci0KLQkJcmMgPSByZWdtYXBfdXBkYXRlX2JpdHMod2xlZC0+cmVnbWFwLAotCQkJ CXdsZWQtPmFkZHIgKyBXTEVEM19TSU5LX1JFR19DVVJSX1NJTkssCi0JCQkJV0xFRDNfU0lOS19S RUdfQ1VSUl9TSU5LX01BU0ssIGFsbCk7Ci0JCWlmIChyYykKLQkJCXJldHVybiByYzsKLQl9Ci0K IAlmb3IgKGkgPSAwOyBpIDwgd2xlZC0+Y2ZnLm51bV9zdHJpbmdzOyArK2kpIHsKLQkJdTE2IGFk ZHIgPSB3bGVkLT5hZGRyICsgV0xFRDNfU0lOS19SRUdfU1RSX09GRlNFVCAqIGk7Ci0KLQkJcmMg PSByZWdtYXBfdXBkYXRlX2JpdHMod2xlZC0+cmVnbWFwLAotCQkJCWFkZHIgKyBXTEVEM19TSU5L X1JFR19TVFJfTU9EX0VOX0JBU0UsCi0JCQkJV0xFRDNfU0lOS19SRUdfU1RSX01PRF9NQVNLLAot CQkJCVdMRUQzX1NJTktfUkVHX1NUUl9NT0RfRU4pOworCQlqID0gd2xlZC0+Y2ZnLmVuYWJsZWRf c3RyaW5nc1tpXTsKKwkJYWRkciA9IHdsZWQtPmN0cmxfYWRkciArIFdMRUQzX1NJTktfUkVHX1NU Ul9NT0RfRU4oaik7CisJCXJjID0gcmVnbWFwX3VwZGF0ZV9iaXRzKHdsZWQtPnJlZ21hcCwgYWRk ciwKKwkJCQkJV0xFRDNfU0lOS19SRUdfU1RSX01PRF9NQVNLLAorCQkJCQlXTEVEM19TSU5LX1JF R19TVFJfTU9EX01BU0spOwogCQlpZiAocmMpCiAJCQlyZXR1cm4gcmM7CiAKIAkJaWYgKHdsZWQt PmNmZy5leHRfZ2VuKSB7Ci0JCQlyYyA9IHJlZ21hcF91cGRhdGVfYml0cyh3bGVkLT5yZWdtYXAs Ci0JCQkJCWFkZHIgKyBXTEVEM19TSU5LX1JFR19TVFJfTU9EX1NSQ19CQVNFLAotCQkJCQlXTEVE M19TSU5LX1JFR19TVFJfTU9EX1NSQ19NQVNLLAotCQkJCQlXTEVEM19TSU5LX1JFR19TVFJfTU9E X1NSQ19FWFQpOworCQkJYWRkciA9IHdsZWQtPmN0cmxfYWRkciArIFdMRUQzX1NJTktfUkVHX1NU Ul9NT0RfU1JDKGopOworCQkJcmMgPSByZWdtYXBfdXBkYXRlX2JpdHMod2xlZC0+cmVnbWFwLCBh ZGRyLAorCQkJCQkJV0xFRDNfU0lOS19SRUdfU1RSX01PRF9TUkNfTUFTSywKKwkJCQkJCVdMRUQz X1NJTktfUkVHX1NUUl9NT0RfU1JDX0VYVCk7CiAJCQlpZiAocmMpCiAJCQkJcmV0dXJuIHJjOwog CQl9CiAKLQkJcmMgPSByZWdtYXBfdXBkYXRlX2JpdHMod2xlZC0+cmVnbWFwLAotCQkJCWFkZHIg KyBXTEVEM19TSU5LX1JFR19TVFJfRlVMTF9TQ0FMRV9DVVJSLAotCQkJCVdMRUQzX1NJTktfUkVH X1NUUl9GVUxMX1NDQUxFX0NVUlJfTUFTSywKLQkJCQl3bGVkLT5jZmcuc3RyaW5nX2lfbGltaXQp OworCQlhZGRyID0gd2xlZC0+Y3RybF9hZGRyICsgV0xFRDNfU0lOS19SRUdfU1RSX0ZVTExfU0NB TEVfQ1VSUihqKTsKKwkJcmMgPSByZWdtYXBfdXBkYXRlX2JpdHMod2xlZC0+cmVnbWFwLCBhZGRy LAorCQkJCQlXTEVEM19TSU5LX1JFR19TVFJfRlVMTF9TQ0FMRV9DVVJSX01BU0ssCisJCQkJCXds ZWQtPmNmZy5zdHJpbmdfaV9saW1pdCk7CiAJCWlmIChyYykKIAkJCXJldHVybiByYzsKIAotCQly YyA9IHJlZ21hcF91cGRhdGVfYml0cyh3bGVkLT5yZWdtYXAsCi0JCQkJYWRkciArIFdMRUQzX1NJ TktfUkVHX1NUUl9DQUJDX0JBU0UsCi0JCQkJV0xFRDNfU0lOS19SRUdfU1RSX0NBQkNfTUFTSywK LQkJCQl3bGVkLT5jZmcuY2FiY19lbiA/Ci0JCQkJCVdMRUQzX1NJTktfUkVHX1NUUl9DQUJDX0VO IDogMCk7CisJCWFkZHIgPSB3bGVkLT5jdHJsX2FkZHIgKyBXTEVEM19TSU5LX1JFR19TVFJfQ0FC QyhqKTsKKwkJcmMgPSByZWdtYXBfdXBkYXRlX2JpdHMod2xlZC0+cmVnbWFwLCBhZGRyLAorCQkJ CQlXTEVEM19TSU5LX1JFR19TVFJfQ0FCQ19NQVNLLAorCQkJCQl3bGVkLT5jZmcuY2FiYyA/CisJ CQkJCVdMRUQzX1NJTktfUkVHX1NUUl9DQUJDX01BU0sgOiAwKTsKIAkJaWYgKHJjKQogCQkJcmV0 dXJuIHJjOworCisJCXNpbmtfZW4gfD0gQklUKGogKyBXTEVEM19TSU5LX1JFR19DVVJSX1NJTktf U0hGVCk7CiAJfQogCisJcmMgPSByZWdtYXBfdXBkYXRlX2JpdHMod2xlZC0+cmVnbWFwLAorCQkJ CXdsZWQtPmN0cmxfYWRkciArIFdMRUQzX1NJTktfUkVHX0NVUlJfU0lOSywKKwkJCQlXTEVEM19T SU5LX1JFR19DVVJSX1NJTktfTUFTSywgc2lua19lbik7CisJaWYgKHJjKQorCQlyZXR1cm4gcmM7 CisKIAlyZXR1cm4gMDsKIH0KIApAQCAtMjAwLDE3ICsyNTksMTIgQEAgc3RhdGljIGludCB3bGVk X3NldHVwKHN0cnVjdCB3bGVkICp3bGVkKQogCS5ib29zdF9pX2xpbWl0ID0gMywKIAkuc3RyaW5n X2lfbGltaXQgPSAyMCwKIAkub3ZwID0gMiwKKwkubnVtX3N0cmluZ3MgPSAzLAogCS5zd2l0Y2hf ZnJlcSA9IDUsCi0JLm51bV9zdHJpbmdzID0gMCwKIAkuY3Nfb3V0X2VuID0gZmFsc2UsCiAJLmV4 dF9nZW4gPSBmYWxzZSwKLQkuY2FiY19lbiA9IGZhbHNlLAotfTsKLQotc3RydWN0IHdsZWRfdmFy X2NmZyB7Ci0JY29uc3QgdTMyICp2YWx1ZXM7Ci0JdTMyICgqZm4pKHUzMik7Ci0JaW50IHNpemU7 CisJLmNhYmMgPSBmYWxzZSwKKwkuZW5hYmxlZF9zdHJpbmdzID0gezAsIDEsIDIsIDN9LAogfTsK IAogc3RhdGljIGNvbnN0IHUzMiB3bGVkM19ib29zdF9pX2xpbWl0X3ZhbHVlc1tdID0gewpAQCAt MjU1LDcgKzMwOSwxMSBAQCBzdGF0aWMgdTMyIHdsZWQzX3N3aXRjaF9mcmVxX3ZhbHVlc19mbih1 MzIgaWR4KQogCS5zaXplID0gMjYsCiB9OwogCi1zdGF0aWMgdTMyIHdsZWQzX3ZhbHVlcyhjb25z dCBzdHJ1Y3Qgd2xlZF92YXJfY2ZnICpjZmcsIHUzMiBpZHgpCitzdGF0aWMgY29uc3Qgc3RydWN0 IHdsZWRfdmFyX2NmZyB3bGVkM19zdHJpbmdfY2ZnID0geworCS5zaXplID0gOCwKK307CisKK3N0 YXRpYyB1MzIgd2xlZF92YWx1ZXMoY29uc3Qgc3RydWN0IHdsZWRfdmFyX2NmZyAqY2ZnLCB1MzIg aWR4KQogewogCWlmIChpZHggPj0gY2ZnLT5zaXplKQogCQlyZXR1cm4gVUlOVF9NQVg7CkBAIC0y NjYsNjggKzMyNCw3NSBAQCBzdGF0aWMgdTMyIHdsZWQzX3ZhbHVlcyhjb25zdCBzdHJ1Y3Qgd2xl ZF92YXJfY2ZnICpjZmcsIHUzMiBpZHgpCiAJcmV0dXJuIGlkeDsKIH0KIAotc3RhdGljIGludCB3 bGVkX2NvbmZpZ3VyZShzdHJ1Y3Qgd2xlZCAqd2xlZCwgc3RydWN0IGRldmljZSAqZGV2KQorc3Rh dGljIGludCB3bGVkX2NvbmZpZ3VyZShzdHJ1Y3Qgd2xlZCAqd2xlZCwgaW50IHZlcnNpb24pCiB7 CiAJc3RydWN0IHdsZWRfY29uZmlnICpjZmcgPSAmd2xlZC0+Y2ZnOwotCXUzMiB2YWw7Ci0JaW50 IHJjOwotCXUzMiBjOwotCWludCBpOwotCWludCBqOwotCi0JY29uc3Qgc3RydWN0IHsKLQkJY29u c3QgY2hhciAqbmFtZTsKLQkJdTMyICp2YWxfcHRyOwotCQljb25zdCBzdHJ1Y3Qgd2xlZF92YXJf Y2ZnICpjZmc7Ci0JfSB1MzJfb3B0c1tdID0geworCXN0cnVjdCBkZXZpY2UgKmRldiA9IHdsZWQt PmRldjsKKwljb25zdCBfX2JlMzIgKnByb3BfYWRkcjsKKwl1MzIgc2l6ZSwgdmFsLCBjLCBzdHJp bmdfbGVuOworCWludCByYywgaSwgajsKKworCWNvbnN0IHN0cnVjdCB3bGVkX3UzMl9vcHRzICp1 MzJfb3B0cyA9IE5VTEw7CisJY29uc3Qgc3RydWN0IHdsZWRfdTMyX29wdHMgd2xlZDNfb3B0c1td ID0gewogCQl7Ci0JCQkicWNvbSxjdXJyZW50LWJvb3N0LWxpbWl0IiwKLQkJCSZjZmctPmJvb3N0 X2lfbGltaXQsCisJCQkubmFtZSA9ICJxY29tLGN1cnJlbnQtYm9vc3QtbGltaXQiLAorCQkJLnZh bF9wdHIgPSAmY2ZnLT5ib29zdF9pX2xpbWl0LAogCQkJLmNmZyA9ICZ3bGVkM19ib29zdF9pX2xp bWl0X2NmZywKIAkJfSwKIAkJewotCQkJInFjb20sY3VycmVudC1saW1pdCIsCi0JCQkmY2ZnLT5z dHJpbmdfaV9saW1pdCwKKwkJCS5uYW1lID0gInFjb20sY3VycmVudC1saW1pdCIsCisJCQkudmFs X3B0ciA9ICZjZmctPnN0cmluZ19pX2xpbWl0LAogCQkJLmNmZyA9ICZ3bGVkM19zdHJpbmdfaV9s aW1pdF9jZmcsCiAJCX0sCiAJCXsKLQkJCSJxY29tLG92cCIsCi0JCQkmY2ZnLT5vdnAsCisJCQku bmFtZSA9ICJxY29tLG92cCIsCisJCQkudmFsX3B0ciA9ICZjZmctPm92cCwKIAkJCS5jZmcgPSAm d2xlZDNfb3ZwX2NmZywKIAkJfSwKIAkJewotCQkJInFjb20sc3dpdGNoaW5nLWZyZXEiLAotCQkJ JmNmZy0+c3dpdGNoX2ZyZXEsCisJCQkubmFtZSA9ICJxY29tLHN3aXRjaGluZy1mcmVxIiwKKwkJ CS52YWxfcHRyID0gJmNmZy0+c3dpdGNoX2ZyZXEsCiAJCQkuY2ZnID0gJndsZWQzX3N3aXRjaF9m cmVxX2NmZywKIAkJfSwKIAkJewotCQkJInFjb20sbnVtLXN0cmluZ3MiLAotCQkJJmNmZy0+bnVt X3N0cmluZ3MsCisJCQkubmFtZSA9ICJxY29tLG51bS1zdHJpbmdzIiwKKwkJCS52YWxfcHRyID0g JmNmZy0+bnVtX3N0cmluZ3MsCiAJCQkuY2ZnID0gJndsZWQzX251bV9zdHJpbmdzX2NmZywKIAkJ fSwKIAl9OwotCWNvbnN0IHN0cnVjdCB7Ci0JCWNvbnN0IGNoYXIgKm5hbWU7Ci0JCWJvb2wgKnZh bF9wdHI7Ci0JfSBib29sX29wdHNbXSA9IHsKKworCWNvbnN0IHN0cnVjdCB3bGVkX2Jvb2xfb3B0 cyBib29sX29wdHNbXSA9IHsKIAkJeyAicWNvbSxjcy1vdXQiLCAmY2ZnLT5jc19vdXRfZW4sIH0s CiAJCXsgInFjb20sZXh0LWdlbiIsICZjZmctPmV4dF9nZW4sIH0sCi0JCXsgInFjb20sY2FiYyIs ICZjZmctPmNhYmNfZW4sIH0sCisJCXsgInFjb20sY2FiYyIsICZjZmctPmNhYmMsIH0sCiAJfTsK IAotCXJjID0gb2ZfcHJvcGVydHlfcmVhZF91MzIoZGV2LT5vZl9ub2RlLCAicmVnIiwgJnZhbCk7 Ci0JaWYgKHJjIHx8IHZhbCA+IDB4ZmZmZikgewotCQlkZXZfZXJyKGRldiwgImludmFsaWQgSU8g cmVzb3VyY2VzXG4iKTsKLQkJcmV0dXJuIHJjID8gcmMgOiAtRUlOVkFMOworCXByb3BfYWRkciA9 IG9mX2dldF9hZGRyZXNzKGRldi0+b2Zfbm9kZSwgMCwgTlVMTCwgTlVMTCk7CisJaWYgKCFwcm9w X2FkZHIpIHsKKwkJZGV2X2Vycih3bGVkLT5kZXYsICJpbnZhbGlkIElPIHJlc291cmNlc1xuIik7 CisJCXJldHVybiAtRUlOVkFMOwogCX0KLQl3bGVkLT5hZGRyID0gdmFsOworCXdsZWQtPmN0cmxf YWRkciA9IGJlMzJfdG9fY3B1KCpwcm9wX2FkZHIpOwogCiAJcmMgPSBvZl9wcm9wZXJ0eV9yZWFk X3N0cmluZyhkZXYtPm9mX25vZGUsICJsYWJlbCIsICZ3bGVkLT5uYW1lKTsKIAlpZiAocmMpCiAJ CXdsZWQtPm5hbWUgPSBkZXZtX2thc3ByaW50ZihkZXYsIEdGUF9LRVJORUwsICIlcE9GbiIsIGRl di0+b2Zfbm9kZSk7CiAKLQkqY2ZnID0gd2xlZDNfY29uZmlnX2RlZmF1bHRzOwotCWZvciAoaSA9 IDA7IGkgPCBBUlJBWV9TSVpFKHUzMl9vcHRzKTsgKytpKSB7CisJc3dpdGNoICh2ZXJzaW9uKSB7 CisJY2FzZSAzOgorCQl1MzJfb3B0cyA9IHdsZWQzX29wdHM7CisJCXNpemUgPSBBUlJBWV9TSVpF KHdsZWQzX29wdHMpOworCQkqY2ZnID0gd2xlZDNfY29uZmlnX2RlZmF1bHRzOworCQl3bGVkLT53 bGVkX3NldF9icmlnaHRuZXNzID0gd2xlZDNfc2V0X2JyaWdodG5lc3M7CisJCXdsZWQtPm1heF9z dHJpbmdfY291bnQgPSAzOworCQlicmVhazsKKworCWRlZmF1bHQ6CisJCWRldl9lcnIod2xlZC0+ ZGV2LCAiSW52YWxpZCBXTEVEIHZlcnNpb25cbiIpOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisK Kwlmb3IgKGkgPSAwOyBpIDwgc2l6ZTsgKytpKSB7CiAJCXJjID0gb2ZfcHJvcGVydHlfcmVhZF91 MzIoZGV2LT5vZl9ub2RlLCB1MzJfb3B0c1tpXS5uYW1lLCAmdmFsKTsKIAkJaWYgKHJjID09IC1F SU5WQUwpIHsKIAkJCWNvbnRpbnVlOwpAQCAtMzM4LDEyICs0MDMsMTUgQEAgc3RhdGljIGludCB3 bGVkX2NvbmZpZ3VyZShzdHJ1Y3Qgd2xlZCAqd2xlZCwgc3RydWN0IGRldmljZSAqZGV2KQogCiAJ CWMgPSBVSU5UX01BWDsKIAkJZm9yIChqID0gMDsgYyAhPSB2YWw7IGorKykgewotCQkJYyA9IHds ZWQzX3ZhbHVlcyh1MzJfb3B0c1tpXS5jZmcsIGopOworCQkJYyA9IHdsZWRfdmFsdWVzKHUzMl9v cHRzW2ldLmNmZywgaik7CiAJCQlpZiAoYyA9PSBVSU5UX01BWCkgewogCQkJCWRldl9lcnIoZGV2 LCAiaW52YWxpZCB2YWx1ZSBmb3IgJyVzJ1xuIiwKIAkJCQkJdTMyX29wdHNbaV0ubmFtZSk7CiAJ CQkJcmV0dXJuIC1FSU5WQUw7CiAJCQl9CisKKwkJCWlmIChjID09IHZhbCkKKwkJCQlicmVhazsK IAkJfQogCiAJCWRldl9kYmcoZGV2LCAiJyVzJyA9ICV1XG4iLCB1MzJfb3B0c1tpXS5uYW1lLCBj KTsKQEAgLTM1Nyw2ICs0MjUsMTUgQEAgc3RhdGljIGludCB3bGVkX2NvbmZpZ3VyZShzdHJ1Y3Qg d2xlZCAqd2xlZCwgc3RydWN0IGRldmljZSAqZGV2KQogCiAJY2ZnLT5udW1fc3RyaW5ncyA9IGNm Zy0+bnVtX3N0cmluZ3MgKyAxOwogCisJc3RyaW5nX2xlbiA9IG9mX3Byb3BlcnR5X2NvdW50X2Vs ZW1zX29mX3NpemUoZGV2LT5vZl9ub2RlLAorCQkJCQkJICAgICAicWNvbSxlbmFibGVkLXN0cmlu Z3MiLAorCQkJCQkJICAgICBzaXplb2YodTMyKSk7CisJaWYgKHN0cmluZ19sZW4gPiAwKQorCQlv Zl9wcm9wZXJ0eV9yZWFkX3UzMl9hcnJheShkZXYtPm9mX25vZGUsCisJCQkJCQkicWNvbSxlbmFi bGVkLXN0cmluZ3MiLAorCQkJCQkJd2xlZC0+Y2ZnLmVuYWJsZWRfc3RyaW5ncywKKwkJCQkJCXNp emVvZih1MzIpKTsKKwogCXJldHVybiAwOwogfQogCkBAIC0zNzAsNiArNDQ3LDcgQEAgc3RhdGlj IGludCB3bGVkX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCiAJc3RydWN0IGJh Y2tsaWdodF9kZXZpY2UgKmJsOwogCXN0cnVjdCB3bGVkICp3bGVkOwogCXN0cnVjdCByZWdtYXAg KnJlZ21hcDsKKwlpbnQgdmVyc2lvbjsKIAl1MzIgdmFsOwogCWludCByYzsKIApAQCAtMzg0LDE1 ICs0NjIsMzIgQEAgc3RhdGljIGludCB3bGVkX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2Ug KnBkZXYpCiAJCXJldHVybiAtRU5PTUVNOwogCiAJd2xlZC0+cmVnbWFwID0gcmVnbWFwOworCXds ZWQtPmRldiA9ICZwZGV2LT5kZXY7CiAKLQlyYyA9IHdsZWRfY29uZmlndXJlKHdsZWQsICZwZGV2 LT5kZXYpOwotCWlmIChyYykKLQkJcmV0dXJuIHJjOworCXZlcnNpb24gPSAodWludHB0cl90KW9m X2RldmljZV9nZXRfbWF0Y2hfZGF0YSgmcGRldi0+ZGV2KTsKKwlpZiAoIXZlcnNpb24pIHsKKwkJ ZGV2X2VycigmcGRldi0+ZGV2LCAiVW5rbm93biBkZXZpY2UgdmVyc2lvblxuIik7CisJCXJldHVy biAtRU5PREVWOworCX0KIAotCXJjID0gd2xlZF9zZXR1cCh3bGVkKTsKKwlyYyA9IHdsZWRfY29u ZmlndXJlKHdsZWQsIHZlcnNpb24pOwogCWlmIChyYykKIAkJcmV0dXJuIHJjOwogCisJc3dpdGNo ICh2ZXJzaW9uKSB7CisJY2FzZSAzOgorCQlyYyA9IHdsZWQzX3NldHVwKHdsZWQpOworCQlpZiAo cmMpIHsKKwkJCWRldl9lcnIoJnBkZXYtPmRldiwgIndsZWQzX3NldHVwIGZhaWxlZFxuIik7CisJ CQlyZXR1cm4gcmM7CisJCX0KKwkJYnJlYWs7CisKKwlkZWZhdWx0OgorCQlkZXZfZXJyKHdsZWQt PmRldiwgIkludmFsaWQgV0xFRCB2ZXJzaW9uXG4iKTsKKwkJYnJlYWs7CisJfQorCiAJdmFsID0g V0xFRF9ERUZBVUxUX0JSSUdIVE5FU1M7CiAJb2ZfcHJvcGVydHlfcmVhZF91MzIocGRldi0+ZGV2 Lm9mX25vZGUsICJkZWZhdWx0LWJyaWdodG5lc3MiLCAmdmFsKTsKIApAQCAtNDA3LDcgKzUwMiw3 IEBAIHN0YXRpYyBpbnQgd2xlZF9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQog fTsKIAogc3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2VfaWQgd2xlZF9tYXRjaF90YWJsZVtd ID0gewotCXsgLmNvbXBhdGlibGUgPSAicWNvbSxwbTg5NDEtd2xlZCIgfSwKKwl7IC5jb21wYXRp YmxlID0gInFjb20scG04OTQxLXdsZWQiLCAuZGF0YSA9ICh2b2lkICopMyB9LAogCXt9CiB9Owog TU9EVUxFX0RFVklDRV9UQUJMRShvZiwgd2xlZF9tYXRjaF90YWJsZSk7Ci0tIApUaGUgUXVhbGNv bW0gSW5ub3ZhdGlvbiBDZW50ZXIsIEluYy4gaXMgYSBtZW1iZXIgb2YgdGhlIENvZGUgQXVyb3Jh IEZvcnVtLAogYSBMaW51eCBGb3VuZGF0aW9uIENvbGxhYm9yYXRpdmUgUHJvamVjdAoKX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KZHJpLWRldmVsIG1haWxp bmcgbGlzdApkcmktZGV2ZWxAbGlzdHMuZnJlZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlzdHMuZnJl ZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGluZm8vZHJpLWRldmVs