From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754348AbbATTop (ORCPT ); Tue, 20 Jan 2015 14:44:45 -0500 Received: from smtp6-g21.free.fr ([212.27.42.6]:25269 "EHLO smtp6-g21.free.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754250AbbATTom (ORCPT ); Tue, 20 Jan 2015 14:44:42 -0500 X-Mailbox-Line: From ddd1b299eca187ab2fa9b119da2ec8297ead1a66 Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: References: From: Jean-Francois Moine Date: Tue, 20 Jan 2015 20:16:25 +0100 Subject: [PATCH v10 9/9] ASoC: add generic dt-card support To: Mark Brown , Russell King - ARM Linux Cc: Dave Airlie , Andrew Jackson , Jyri Sarha , alsa-devel@alsa-project.org, devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org To create simple cards, the syntax of the simple-card does not follow the common binding of the device graphs (Documentation/devicetree/bindings/graph.txt). dt-card devices are created by audio controllers with themselves as the root of the graph. The sound card is created according to the parameters found in the tree. Signed-off-by: Jean-Francois Moine --- sound/soc/generic/Kconfig | 2 + sound/soc/generic/Makefile | 2 + sound/soc/generic/dt-card.c | 275 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 279 insertions(+) create mode 100644 sound/soc/generic/dt-card.c diff --git a/sound/soc/generic/Kconfig b/sound/soc/generic/Kconfig index 610f612..9c5e1e2 100644 --- a/sound/soc/generic/Kconfig +++ b/sound/soc/generic/Kconfig @@ -2,3 +2,5 @@ config SND_SIMPLE_CARD tristate "ASoC Simple sound card support" help This option enables generic simple sound card support +config SND_DT_CARD + tristate diff --git a/sound/soc/generic/Makefile b/sound/soc/generic/Makefile index 9c3b246..56834a9 100644 --- a/sound/soc/generic/Makefile +++ b/sound/soc/generic/Makefile @@ -1,3 +1,5 @@ snd-soc-simple-card-objs := simple-card.o +snd-soc-dt-card-objs := dt-card.o obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o +obj-$(CONFIG_SND_DT_CARD) += snd-soc-dt-card.o diff --git a/sound/soc/generic/dt-card.c b/sound/soc/generic/dt-card.c new file mode 100644 index 0000000..6a5de2f --- /dev/null +++ b/sound/soc/generic/dt-card.c @@ -0,0 +1,275 @@ +/* + * ALSA SoC DT based sound card support + * + * Copyright (C) 2015 Jean-Francois Moine + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +/* check if a node is an audio port */ +static int asoc_dt_card_is_audio_port(struct device_node *of_port) +{ + const char *name; + int ret; + + if (!of_port->name || + of_node_cmp(of_port->name, "port") != 0) + return 0; + ret = of_property_read_string(of_port, + "port-type", + &name); + if (!ret && + (strcmp(name, "i2s") == 0 || + strcmp(name, "spdif") == 0)) + return 1; + return 0; +} + +/* + * Get the DAI number from the DT by counting the audio ports + * of the remote device node (codec). + */ +static int asoc_dt_card_get_dai_number(struct device_node *of_codec, + struct device_node *of_remote_endpoint) +{ + struct device_node *of_port, *of_endpoint; + int ndai; + + ndai = 0; + for_each_child_of_node(of_codec, of_port) { + if (!asoc_dt_card_is_audio_port(of_port)) + continue; + for_each_child_of_node(of_port, of_endpoint) { + if (!of_endpoint->name || + of_node_cmp(of_endpoint->name, "endpoint") != 0) + continue; + if (of_endpoint == of_remote_endpoint) { + of_node_put(of_port); + of_node_put(of_endpoint); + return ndai; + } + } + ndai++; + } + return 0; /* should never be reached */ +} + +/* + * Parse a graph of audio ports + * @dev: Card device + * @of_cpu: Device node of the audio controller + * @card: Card definition + * + * Builds the DAI links of the card from the DT graph of audio ports + * starting from the audio controller. + * It does not handle the port groups. + * The CODEC device nodes in the DAI links must be dereferenced by the caller. + * + * Returns the number of DAI links or (< 0) on error + */ +static int asoc_dt_card_of_parse_graph(struct device *dev, + struct device_node *of_cpu, + struct snd_soc_card *card) +{ + struct device_node *of_codec, *of_port, *of_endpoint, + *of_remote_endpoint; + struct snd_soc_dai_link *link; + struct snd_soc_dai_link_component *component; + struct of_phandle_args args, args2; + int ret, ilink, icodec, nlinks, ncodecs; + + /* count the number of DAI links */ + nlinks = 0; + for_each_child_of_node(of_cpu, of_port) { + if (asoc_dt_card_is_audio_port(of_port)) + nlinks++; + } + + /* allocate the DAI link array */ + link = devm_kzalloc(dev, sizeof(*link) * nlinks, GFP_KERNEL); + if (!link) + return -ENOMEM; + card->dai_link = link; + + /* build the DAI links */ + ilink = 0; + args.np = of_cpu; + args.args_count = 1; + for_each_child_of_node(of_cpu, of_port) { + if (!asoc_dt_card_is_audio_port(of_port)) + continue; + + link->platform_of_node = + link->cpu_of_node = of_cpu; + args.args[0] = ilink; + ret = snd_soc_get_dai_name(&args, &link->cpu_dai_name); + if (ret) { + dev_err(dev, "no CPU DAI name for link %d!\n", + ilink); + continue; + } + + /* count the number of codecs of this DAI link */ + ncodecs = 0; + for_each_child_of_node(of_port, of_endpoint) { + if (of_parse_phandle(of_endpoint, + "remote-endpoint", 0)) + ncodecs++; + } + if (ncodecs == 0) + continue; + component = devm_kzalloc(dev, + sizeof(*component) * ncodecs, + GFP_KERNEL); + if (!component) + return -ENOMEM; + link->codecs = component; + + icodec = 0; + args2.args_count = 1; + for_each_child_of_node(of_port, of_endpoint) { + of_remote_endpoint = of_parse_phandle(of_endpoint, + "remote-endpoint", 0); + if (!of_remote_endpoint) + continue; + component->of_node = of_codec = + of_remote_endpoint->parent->parent; + args2.np = of_codec; + args2.args[0] = asoc_dt_card_get_dai_number(of_codec, + of_remote_endpoint); + ret = snd_soc_get_dai_name(&args2, + &component->dai_name); + if (ret) { + if (ret == -EPROBE_DEFER) { + card->num_links = ilink + 1; + link->num_codecs = icodec; + return ret; + } + dev_err(dev, + "no CODEC DAI name for link %d\n", + ilink); + continue; + } + of_node_get(of_codec); + + icodec++; + if (icodec >= ncodecs) + break; + component++; + } + if (icodec == 0) + continue; + link->num_codecs = icodec; + + ilink++; + if (ilink >= nlinks) + break; + link++; + } + card->num_links = ilink; + + return ilink; +} + +static void asoc_dt_card_unref(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct snd_soc_dai_link *link; + int nlinks, ncodecs; + + if (card) { + for (nlinks = 0, link = card->dai_link; + nlinks < card->num_links; + nlinks++, link++) { + for (ncodecs = 0; + ncodecs < link->num_codecs; + ncodecs++) + of_node_put(card->dai_link->codecs[ncodecs].of_node); + } + } +} + +/* + * The platform data contains the pointer to the device node + * which starts the description of the graph of the audio ports, + * This device node is usually the audio controller. + */ +static int asoc_dt_card_probe(struct platform_device *pdev) +{ + struct device_node **p_np = pdev->dev.platform_data; + struct device_node *of_cpu = *p_np; + struct snd_soc_card *card; + struct snd_soc_dai_link *link; + char *name; + int ret, i; + + card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; + ret = asoc_dt_card_of_parse_graph(&pdev->dev, of_cpu, card); + if (ret < 0) + goto err; + + /* fill the remaining values of the card */ + card->owner = THIS_MODULE; + card->dev = &pdev->dev; + card->name = "DT-card"; + for (i = 0, link = card->dai_link; + i < card->num_links; + i++, link++) { + name = devm_kzalloc(&pdev->dev, + strlen(link->cpu_dai_name) + + strlen(link->codecs[0].dai_name) + + 2, + GFP_KERNEL); + if (!name) { + ret = -ENOMEM; + goto err; + } + sprintf(name, "%s-%s", link->cpu_dai_name, + link->codecs[0].dai_name); + link->name = link->stream_name = name; + } + + card->dai_link->dai_fmt = + snd_soc_of_parse_daifmt(of_cpu, "dt-audio-card,", + NULL, NULL) & + ~SND_SOC_DAIFMT_MASTER_MASK; + + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret >= 0) + return ret; + +err: + asoc_dt_card_unref(pdev); + return ret; +} + +static int asoc_dt_card_remove(struct platform_device *pdev) +{ + asoc_dt_card_unref(pdev); + snd_soc_unregister_card(platform_get_drvdata(pdev)); + return 0; +} + +static struct platform_driver asoc_dt_card = { + .driver = { + .name = "asoc-dt-card", + }, + .probe = asoc_dt_card_probe, + .remove = asoc_dt_card_remove, +}; + +module_platform_driver(asoc_dt_card); + +MODULE_ALIAS("platform:asoc-dt-card"); +MODULE_DESCRIPTION("ASoC DT Sound Card"); +MODULE_AUTHOR("Jean-Francois Moine "); +MODULE_LICENSE("GPL"); -- 2.1.4 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jean-Francois Moine Subject: [PATCH v10 9/9] ASoC: add generic dt-card support Date: Tue, 20 Jan 2015 20:16:25 +0100 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Mark Brown , Russell King - ARM Linux Cc: devicetree@vger.kernel.org, alsa-devel@alsa-project.org, Andrew Jackson , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Jyri Sarha List-Id: devicetree@vger.kernel.org VG8gY3JlYXRlIHNpbXBsZSBjYXJkcywgdGhlIHN5bnRheCBvZiB0aGUgc2ltcGxlLWNhcmQgZG9l cyBub3QgZm9sbG93CnRoZSBjb21tb24gYmluZGluZyBvZiB0aGUgZGV2aWNlIGdyYXBocwooRG9j dW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL2dyYXBoLnR4dCkuCgpkdC1jYXJkIGRldmlj ZXMgYXJlIGNyZWF0ZWQgYnkgYXVkaW8gY29udHJvbGxlcnMgd2l0aCB0aGVtc2VsdmVzIGFzIHRo ZQpyb290IG9mIHRoZSBncmFwaC4gVGhlIHNvdW5kIGNhcmQgaXMgY3JlYXRlZCBhY2NvcmRpbmcg dG8gdGhlIHBhcmFtZXRlcnMKZm91bmQgaW4gdGhlIHRyZWUuCgpTaWduZWQtb2ZmLWJ5OiBKZWFu LUZyYW5jb2lzIE1vaW5lIDxtb2luZWpmQGZyZWUuZnI+Ci0tLQogc291bmQvc29jL2dlbmVyaWMv S2NvbmZpZyAgIHwgICAyICsKIHNvdW5kL3NvYy9nZW5lcmljL01ha2VmaWxlICB8ICAgMiArCiBz b3VuZC9zb2MvZ2VuZXJpYy9kdC1jYXJkLmMgfCAyNzUgKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKysrKysrKysKIDMgZmlsZXMgY2hhbmdlZCwgMjc5IGluc2VydGlvbnMoKykK IGNyZWF0ZSBtb2RlIDEwMDY0NCBzb3VuZC9zb2MvZ2VuZXJpYy9kdC1jYXJkLmMKCmRpZmYgLS1n aXQgYS9zb3VuZC9zb2MvZ2VuZXJpYy9LY29uZmlnIGIvc291bmQvc29jL2dlbmVyaWMvS2NvbmZp ZwppbmRleCA2MTBmNjEyLi45YzVlMWUyIDEwMDY0NAotLS0gYS9zb3VuZC9zb2MvZ2VuZXJpYy9L Y29uZmlnCisrKyBiL3NvdW5kL3NvYy9nZW5lcmljL0tjb25maWcKQEAgLTIsMyArMiw1IEBAIGNv bmZpZyBTTkRfU0lNUExFX0NBUkQKIAl0cmlzdGF0ZSAiQVNvQyBTaW1wbGUgc291bmQgY2FyZCBz dXBwb3J0IgogCWhlbHAKIAkgIFRoaXMgb3B0aW9uIGVuYWJsZXMgZ2VuZXJpYyBzaW1wbGUgc291 bmQgY2FyZCBzdXBwb3J0Citjb25maWcgU05EX0RUX0NBUkQKKwl0cmlzdGF0ZQpkaWZmIC0tZ2l0 IGEvc291bmQvc29jL2dlbmVyaWMvTWFrZWZpbGUgYi9zb3VuZC9zb2MvZ2VuZXJpYy9NYWtlZmls ZQppbmRleCA5YzNiMjQ2Li41NjgzNGE5IDEwMDY0NAotLS0gYS9zb3VuZC9zb2MvZ2VuZXJpYy9N YWtlZmlsZQorKysgYi9zb3VuZC9zb2MvZ2VuZXJpYy9NYWtlZmlsZQpAQCAtMSwzICsxLDUgQEAK IHNuZC1zb2Mtc2ltcGxlLWNhcmQtb2Jqcwk6PSBzaW1wbGUtY2FyZC5vCitzbmQtc29jLWR0LWNh cmQtb2JqcwkJOj0gZHQtY2FyZC5vCiAKIG9iai0kKENPTkZJR19TTkRfU0lNUExFX0NBUkQpCSs9 IHNuZC1zb2Mtc2ltcGxlLWNhcmQubworb2JqLSQoQ09ORklHX1NORF9EVF9DQVJEKQkrPSBzbmQt c29jLWR0LWNhcmQubwpkaWZmIC0tZ2l0IGEvc291bmQvc29jL2dlbmVyaWMvZHQtY2FyZC5jIGIv c291bmQvc29jL2dlbmVyaWMvZHQtY2FyZC5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAw MDAwMDAuLjZhNWRlMmYKLS0tIC9kZXYvbnVsbAorKysgYi9zb3VuZC9zb2MvZ2VuZXJpYy9kdC1j YXJkLmMKQEAgLTAsMCArMSwyNzUgQEAKKy8qCisgKiBBTFNBIFNvQyBEVCBiYXNlZCBzb3VuZCBj YXJkIHN1cHBvcnQKKyAqCisgKiBDb3B5cmlnaHQgKEMpIDIwMTUgSmVhbi1GcmFuY29pcyBNb2lu ZQorICoKKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJp YnV0ZSBpdCBhbmQvb3IgbW9kaWZ5CisgKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBH ZW5lcmFsIFB1YmxpYyBMaWNlbnNlIHZlcnNpb24gMiBhcworICogcHVibGlzaGVkIGJ5IHRoZSBG cmVlIFNvZnR3YXJlIEZvdW5kYXRpb24uCisgKi8KKworI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5o PgorI2luY2x1ZGUgPHNvdW5kL3NvYy5oPgorI2luY2x1ZGUgPGxpbnV4L29mLmg+CisjaW5jbHVk ZSA8bGludXgvb2ZfZGV2aWNlLmg+CisKKy8qIGNoZWNrIGlmIGEgbm9kZSBpcyBhbiBhdWRpbyBw b3J0ICovCitzdGF0aWMgaW50IGFzb2NfZHRfY2FyZF9pc19hdWRpb19wb3J0KHN0cnVjdCBkZXZp Y2Vfbm9kZSAqb2ZfcG9ydCkKK3sKKwljb25zdCBjaGFyICpuYW1lOworCWludCByZXQ7CisKKwlp ZiAoIW9mX3BvcnQtPm5hbWUgfHwKKwkgICAgb2Zfbm9kZV9jbXAob2ZfcG9ydC0+bmFtZSwgInBv cnQiKSAhPSAwKQorCQlyZXR1cm4gMDsKKwlyZXQgPSBvZl9wcm9wZXJ0eV9yZWFkX3N0cmluZyhv Zl9wb3J0LAorCQkJCQkicG9ydC10eXBlIiwKKwkJCQkJJm5hbWUpOworCWlmICghcmV0ICYmCisJ ICAgIChzdHJjbXAobmFtZSwgImkycyIpID09IDAgfHwKKwkgICAgIHN0cmNtcChuYW1lLCAic3Bk aWYiKSA9PSAwKSkKKwkJcmV0dXJuIDE7CisJcmV0dXJuIDA7Cit9CisKKy8qCisgKiBHZXQgdGhl IERBSSBudW1iZXIgZnJvbSB0aGUgRFQgYnkgY291bnRpbmcgdGhlIGF1ZGlvIHBvcnRzCisgKiBv ZiB0aGUgcmVtb3RlIGRldmljZSBub2RlIChjb2RlYykuCisgKi8KK3N0YXRpYyBpbnQgYXNvY19k dF9jYXJkX2dldF9kYWlfbnVtYmVyKHN0cnVjdCBkZXZpY2Vfbm9kZSAqb2ZfY29kZWMsCisJCQkJ c3RydWN0IGRldmljZV9ub2RlICpvZl9yZW1vdGVfZW5kcG9pbnQpCit7CisJc3RydWN0IGRldmlj ZV9ub2RlICpvZl9wb3J0LCAqb2ZfZW5kcG9pbnQ7CisJaW50IG5kYWk7CisKKwluZGFpID0gMDsK Kwlmb3JfZWFjaF9jaGlsZF9vZl9ub2RlKG9mX2NvZGVjLCBvZl9wb3J0KSB7CisJCWlmICghYXNv Y19kdF9jYXJkX2lzX2F1ZGlvX3BvcnQob2ZfcG9ydCkpCisJCQljb250aW51ZTsKKwkJZm9yX2Vh Y2hfY2hpbGRfb2Zfbm9kZShvZl9wb3J0LCBvZl9lbmRwb2ludCkgeworCQkJaWYgKCFvZl9lbmRw b2ludC0+bmFtZSB8fAorCQkJICAgIG9mX25vZGVfY21wKG9mX2VuZHBvaW50LT5uYW1lLCAiZW5k cG9pbnQiKSAhPSAwKQorCQkJCWNvbnRpbnVlOworCQkJaWYgKG9mX2VuZHBvaW50ID09IG9mX3Jl bW90ZV9lbmRwb2ludCkgeworCQkJCW9mX25vZGVfcHV0KG9mX3BvcnQpOworCQkJCW9mX25vZGVf cHV0KG9mX2VuZHBvaW50KTsKKwkJCQlyZXR1cm4gbmRhaTsKKwkJCX0KKwkJfQorCQluZGFpKys7 CisJfQorCXJldHVybiAwOwkJLyogc2hvdWxkIG5ldmVyIGJlIHJlYWNoZWQgKi8KK30KKworLyoK KyAqIFBhcnNlIGEgZ3JhcGggb2YgYXVkaW8gcG9ydHMKKyAqIEBkZXY6IENhcmQgZGV2aWNlCisg KiBAb2ZfY3B1OiBEZXZpY2Ugbm9kZSBvZiB0aGUgYXVkaW8gY29udHJvbGxlcgorICogQGNhcmQ6 IENhcmQgZGVmaW5pdGlvbgorICoKKyAqIEJ1aWxkcyB0aGUgREFJIGxpbmtzIG9mIHRoZSBjYXJk IGZyb20gdGhlIERUIGdyYXBoIG9mIGF1ZGlvIHBvcnRzCisgKiBzdGFydGluZyBmcm9tIHRoZSBh dWRpbyBjb250cm9sbGVyLgorICogSXQgZG9lcyBub3QgaGFuZGxlIHRoZSBwb3J0IGdyb3Vwcy4K KyAqIFRoZSBDT0RFQyBkZXZpY2Ugbm9kZXMgaW4gdGhlIERBSSBsaW5rcyBtdXN0IGJlIGRlcmVm ZXJlbmNlZCBieSB0aGUgY2FsbGVyLgorICoKKyAqIFJldHVybnMgdGhlIG51bWJlciBvZiBEQUkg bGlua3Mgb3IgKDwgMCkgb24gZXJyb3IKKyAqLworc3RhdGljIGludCBhc29jX2R0X2NhcmRfb2Zf cGFyc2VfZ3JhcGgoc3RydWN0IGRldmljZSAqZGV2LAorCQkJCXN0cnVjdCBkZXZpY2Vfbm9kZSAq b2ZfY3B1LAorCQkJCXN0cnVjdCBzbmRfc29jX2NhcmQgKmNhcmQpCit7CisJc3RydWN0IGRldmlj ZV9ub2RlICpvZl9jb2RlYywgKm9mX3BvcnQsICpvZl9lbmRwb2ludCwKKwkJCQkqb2ZfcmVtb3Rl X2VuZHBvaW50OworCXN0cnVjdCBzbmRfc29jX2RhaV9saW5rICpsaW5rOworCXN0cnVjdCBzbmRf c29jX2RhaV9saW5rX2NvbXBvbmVudCAqY29tcG9uZW50OworCXN0cnVjdCBvZl9waGFuZGxlX2Fy Z3MgYXJncywgYXJnczI7CisJaW50IHJldCwgaWxpbmssIGljb2RlYywgbmxpbmtzLCBuY29kZWNz OworCisJLyogY291bnQgdGhlIG51bWJlciBvZiBEQUkgbGlua3MgKi8KKwlubGlua3MgPSAwOwor CWZvcl9lYWNoX2NoaWxkX29mX25vZGUob2ZfY3B1LCBvZl9wb3J0KSB7CisJCWlmIChhc29jX2R0 X2NhcmRfaXNfYXVkaW9fcG9ydChvZl9wb3J0KSkKKwkJCW5saW5rcysrOworCX0KKworCS8qIGFs bG9jYXRlIHRoZSBEQUkgbGluayBhcnJheSAqLworCWxpbmsgPSBkZXZtX2t6YWxsb2MoZGV2LCBz aXplb2YoKmxpbmspICogbmxpbmtzLCBHRlBfS0VSTkVMKTsKKwlpZiAoIWxpbmspCisJCXJldHVy biAtRU5PTUVNOworCWNhcmQtPmRhaV9saW5rID0gbGluazsKKworCS8qIGJ1aWxkIHRoZSBEQUkg bGlua3MgKi8KKwlpbGluayA9IDA7CisJYXJncy5ucCA9IG9mX2NwdTsKKwlhcmdzLmFyZ3NfY291 bnQgPSAxOworCWZvcl9lYWNoX2NoaWxkX29mX25vZGUob2ZfY3B1LCBvZl9wb3J0KSB7CisJCWlm ICghYXNvY19kdF9jYXJkX2lzX2F1ZGlvX3BvcnQob2ZfcG9ydCkpCisJCQljb250aW51ZTsKKwor CQlsaW5rLT5wbGF0Zm9ybV9vZl9ub2RlID0KKwkJCWxpbmstPmNwdV9vZl9ub2RlID0gb2ZfY3B1 OworCQlhcmdzLmFyZ3NbMF0gPSBpbGluazsKKwkJcmV0ID0gc25kX3NvY19nZXRfZGFpX25hbWUo JmFyZ3MsICZsaW5rLT5jcHVfZGFpX25hbWUpOworCQlpZiAocmV0KSB7CisJCQlkZXZfZXJyKGRl diwgIm5vIENQVSBEQUkgbmFtZSBmb3IgbGluayAlZCFcbiIsCisJCQkJaWxpbmspOworCQkJY29u dGludWU7CisJCX0KKworCQkvKiBjb3VudCB0aGUgbnVtYmVyIG9mIGNvZGVjcyBvZiB0aGlzIERB SSBsaW5rICovCisJCW5jb2RlY3MgPSAwOworCQlmb3JfZWFjaF9jaGlsZF9vZl9ub2RlKG9mX3Bv cnQsIG9mX2VuZHBvaW50KSB7CisJCQlpZiAob2ZfcGFyc2VfcGhhbmRsZShvZl9lbmRwb2ludCwK KwkJCQkJInJlbW90ZS1lbmRwb2ludCIsIDApKQorCQkJCW5jb2RlY3MrKzsKKwkJfQorCQlpZiAo bmNvZGVjcyA9PSAwKQorCQkJY29udGludWU7CisJCWNvbXBvbmVudCA9IGRldm1fa3phbGxvYyhk ZXYsCisJCQkJCSBzaXplb2YoKmNvbXBvbmVudCkgKiBuY29kZWNzLAorCQkJCQkgR0ZQX0tFUk5F TCk7CisJCWlmICghY29tcG9uZW50KQorCQkJcmV0dXJuIC1FTk9NRU07CisJCWxpbmstPmNvZGVj cyA9IGNvbXBvbmVudDsKKworCQlpY29kZWMgPSAwOworCQlhcmdzMi5hcmdzX2NvdW50ID0gMTsK KwkJZm9yX2VhY2hfY2hpbGRfb2Zfbm9kZShvZl9wb3J0LCBvZl9lbmRwb2ludCkgeworCQkJb2Zf cmVtb3RlX2VuZHBvaW50ID0gb2ZfcGFyc2VfcGhhbmRsZShvZl9lbmRwb2ludCwKKwkJCQkJCSJy ZW1vdGUtZW5kcG9pbnQiLCAwKTsKKwkJCWlmICghb2ZfcmVtb3RlX2VuZHBvaW50KQorCQkJCWNv bnRpbnVlOworCQkJY29tcG9uZW50LT5vZl9ub2RlID0gb2ZfY29kZWMgPQorCQkJCQlvZl9yZW1v dGVfZW5kcG9pbnQtPnBhcmVudC0+cGFyZW50OworCQkJYXJnczIubnAgPSBvZl9jb2RlYzsKKwkJ CWFyZ3MyLmFyZ3NbMF0gPSBhc29jX2R0X2NhcmRfZ2V0X2RhaV9udW1iZXIob2ZfY29kZWMsCisJ CQkJCQkJb2ZfcmVtb3RlX2VuZHBvaW50KTsKKwkJCXJldCA9IHNuZF9zb2NfZ2V0X2RhaV9uYW1l KCZhcmdzMiwKKwkJCQkJCSAgICZjb21wb25lbnQtPmRhaV9uYW1lKTsKKwkJCWlmIChyZXQpIHsK KwkJCQlpZiAocmV0ID09IC1FUFJPQkVfREVGRVIpIHsKKwkJCQkJY2FyZC0+bnVtX2xpbmtzID0g aWxpbmsgKyAxOworCQkJCQlsaW5rLT5udW1fY29kZWNzID0gaWNvZGVjOworCQkJCQlyZXR1cm4g cmV0OworCQkJCX0KKwkJCQlkZXZfZXJyKGRldiwKKwkJCQkJIm5vIENPREVDIERBSSBuYW1lIGZv ciBsaW5rICVkXG4iLAorCQkJCQlpbGluayk7CisJCQkJY29udGludWU7CisJCQl9CisJCQlvZl9u b2RlX2dldChvZl9jb2RlYyk7CisKKwkJCWljb2RlYysrOworCQkJaWYgKGljb2RlYyA+PSBuY29k ZWNzKQorCQkJCWJyZWFrOworCQkJY29tcG9uZW50Kys7CisJCX0KKwkJaWYgKGljb2RlYyA9PSAw KQorCQkJY29udGludWU7CisJCWxpbmstPm51bV9jb2RlY3MgPSBpY29kZWM7CisKKwkJaWxpbmsr KzsKKwkJaWYgKGlsaW5rID49IG5saW5rcykKKwkJCWJyZWFrOworCQlsaW5rKys7CisJfQorCWNh cmQtPm51bV9saW5rcyA9IGlsaW5rOworCisJcmV0dXJuIGlsaW5rOworfQorCitzdGF0aWMgdm9p ZCBhc29jX2R0X2NhcmRfdW5yZWYoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKK3sKKwlz dHJ1Y3Qgc25kX3NvY19jYXJkICpjYXJkID0gcGxhdGZvcm1fZ2V0X2RydmRhdGEocGRldik7CisJ c3RydWN0IHNuZF9zb2NfZGFpX2xpbmsgKmxpbms7CisJaW50IG5saW5rcywgbmNvZGVjczsKKwor CWlmIChjYXJkKSB7CisJCWZvciAobmxpbmtzID0gMCwgbGluayA9IGNhcmQtPmRhaV9saW5rOwor CQkgICAgIG5saW5rcyA8IGNhcmQtPm51bV9saW5rczsKKwkJICAgICBubGlua3MrKywgbGluaysr KSB7CisJCQlmb3IgKG5jb2RlY3MgPSAwOworCQkJICAgICBuY29kZWNzIDwgbGluay0+bnVtX2Nv ZGVjczsKKwkJCSAgICAgbmNvZGVjcysrKQorCQkJCW9mX25vZGVfcHV0KGNhcmQtPmRhaV9saW5r LT5jb2RlY3NbbmNvZGVjc10ub2Zfbm9kZSk7CisJCX0KKwl9Cit9CisKKy8qCisgKiBUaGUgcGxh dGZvcm0gZGF0YSBjb250YWlucyB0aGUgcG9pbnRlciB0byB0aGUgZGV2aWNlIG5vZGUKKyAqIHdo aWNoIHN0YXJ0cyB0aGUgZGVzY3JpcHRpb24gb2YgdGhlIGdyYXBoIG9mIHRoZSBhdWRpbyBwb3J0 cywKKyAqIFRoaXMgZGV2aWNlIG5vZGUgaXMgdXN1YWxseSB0aGUgYXVkaW8gY29udHJvbGxlci4K KyAqLworc3RhdGljIGludCBhc29jX2R0X2NhcmRfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2Rldmlj ZSAqcGRldikKK3sKKwlzdHJ1Y3QgZGV2aWNlX25vZGUgKipwX25wID0gcGRldi0+ZGV2LnBsYXRm b3JtX2RhdGE7CisJc3RydWN0IGRldmljZV9ub2RlICpvZl9jcHUgPSAqcF9ucDsKKwlzdHJ1Y3Qg c25kX3NvY19jYXJkICpjYXJkOworCXN0cnVjdCBzbmRfc29jX2RhaV9saW5rICpsaW5rOworCWNo YXIgKm5hbWU7CisJaW50IHJldCwgaTsKKworCWNhcmQgPSBkZXZtX2t6YWxsb2MoJnBkZXYtPmRl diwgc2l6ZW9mKCpjYXJkKSwgR0ZQX0tFUk5FTCk7CisJaWYgKCFjYXJkKQorCQlyZXR1cm4gLUVO T01FTTsKKwlyZXQgPSBhc29jX2R0X2NhcmRfb2ZfcGFyc2VfZ3JhcGgoJnBkZXYtPmRldiwgb2Zf Y3B1LCBjYXJkKTsKKwlpZiAocmV0IDwgMCkKKwkJZ290byBlcnI7CisKKwkvKiBmaWxsIHRoZSBy ZW1haW5pbmcgdmFsdWVzIG9mIHRoZSBjYXJkICovCisJY2FyZC0+b3duZXIgPSBUSElTX01PRFVM RTsKKwljYXJkLT5kZXYgPSAmcGRldi0+ZGV2OworCWNhcmQtPm5hbWUgPSAiRFQtY2FyZCI7CisJ Zm9yIChpID0gMCwgbGluayA9IGNhcmQtPmRhaV9saW5rOworCSAgICAgaSA8IGNhcmQtPm51bV9s aW5rczsKKwkgICAgIGkrKywgbGluaysrKSB7CisJCW5hbWUgPSBkZXZtX2t6YWxsb2MoJnBkZXYt PmRldiwKKwkJCQlzdHJsZW4obGluay0+Y3B1X2RhaV9uYW1lKSArCisJCQkJCXN0cmxlbihsaW5r LT5jb2RlY3NbMF0uZGFpX25hbWUpICsKKwkJCQkJMiwKKwkJCQlHRlBfS0VSTkVMKTsKKwkJaWYg KCFuYW1lKSB7CisJCQlyZXQgPSAtRU5PTUVNOworCQkJZ290byBlcnI7CisJCX0KKwkJc3ByaW50 ZihuYW1lLCAiJXMtJXMiLCBsaW5rLT5jcHVfZGFpX25hbWUsCisJCQkJCWxpbmstPmNvZGVjc1sw XS5kYWlfbmFtZSk7CisJCWxpbmstPm5hbWUgPSBsaW5rLT5zdHJlYW1fbmFtZSA9IG5hbWU7CisJ fQorCisJY2FyZC0+ZGFpX2xpbmstPmRhaV9mbXQgPQorCQlzbmRfc29jX29mX3BhcnNlX2RhaWZt dChvZl9jcHUsICJkdC1hdWRpby1jYXJkLCIsCisJCQkJCU5VTEwsIE5VTEwpICYKKwkJCX5TTkRf U09DX0RBSUZNVF9NQVNURVJfTUFTSzsKKworCXJldCA9IGRldm1fc25kX3NvY19yZWdpc3Rlcl9j YXJkKCZwZGV2LT5kZXYsIGNhcmQpOworCWlmIChyZXQgPj0gMCkKKwkJcmV0dXJuIHJldDsKKwor ZXJyOgorCWFzb2NfZHRfY2FyZF91bnJlZihwZGV2KTsKKwlyZXR1cm4gcmV0OworfQorCitzdGF0 aWMgaW50IGFzb2NfZHRfY2FyZF9yZW1vdmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikK K3sKKwlhc29jX2R0X2NhcmRfdW5yZWYocGRldik7CisJc25kX3NvY191bnJlZ2lzdGVyX2NhcmQo cGxhdGZvcm1fZ2V0X2RydmRhdGEocGRldikpOworCXJldHVybiAwOworfQorCitzdGF0aWMgc3Ry dWN0IHBsYXRmb3JtX2RyaXZlciBhc29jX2R0X2NhcmQgPSB7CisJLmRyaXZlciA9IHsKKwkJLm5h bWUgPSAiYXNvYy1kdC1jYXJkIiwKKwl9LAorCS5wcm9iZSA9IGFzb2NfZHRfY2FyZF9wcm9iZSwK KwkucmVtb3ZlID0gYXNvY19kdF9jYXJkX3JlbW92ZSwKK307CisKK21vZHVsZV9wbGF0Zm9ybV9k cml2ZXIoYXNvY19kdF9jYXJkKTsKKworTU9EVUxFX0FMSUFTKCJwbGF0Zm9ybTphc29jLWR0LWNh cmQiKTsKK01PRFVMRV9ERVNDUklQVElPTigiQVNvQyBEVCBTb3VuZCBDYXJkIik7CitNT0RVTEVf QVVUSE9SKCJKZWFuLUZyYW5jb2lzIE1vaW5lIDxtb2luZWpmQGZyZWUuZnI+Iik7CitNT0RVTEVf TElDRU5TRSgiR1BMIik7Ci0tIAoyLjEuNAoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX18KZHJpLWRldmVsIG1haWxpbmcgbGlzdApkcmktZGV2ZWxAbGlzdHMu ZnJlZWRlc2t0b3Aub3JnCmh0dHA6Ly9saXN0cy5mcmVlZGVza3RvcC5vcmcvbWFpbG1hbi9saXN0 aW5mby9kcmktZGV2ZWwK