From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from galahad.ideasonboard.com ([185.26.127.97]:59902 "EHLO galahad.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752500AbdCFAKD (ORCPT ); Sun, 5 Mar 2017 19:10:03 -0500 From: Laurent Pinchart To: dri-devel@lists.freedesktop.org Cc: linux-renesas-soc@vger.kernel.org Subject: [PATCH v3 2/9] drm: rcar-du: Add support for LVDS mode selection Date: Mon, 6 Mar 2017 02:02:55 +0200 Message-Id: <20170306000302.14149-3-laurent.pinchart+renesas@ideasonboard.com> In-Reply-To: <20170306000302.14149-1-laurent.pinchart+renesas@ideasonboard.com> References: <20170306000302.14149-1-laurent.pinchart+renesas@ideasonboard.com> Sender: linux-renesas-soc-owner@vger.kernel.org List-ID: Retrieve the LVDS mode from the panel and configure the LVDS encoder accordingly. LVDS mode selection is static as LVDS panels can't be hot-plugged on any of the device supported by the driver. Support for dynamic mode selection can be implemented in the future when needed. Signed-off-by: Laurent Pinchart --- Changes since v2: - Rebased on top of the DRM_BUS_FLAG_DATA_MIRROR rename. --- drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 27 +++++++++++++++++++++++++++ drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 11 +++++++++-- drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h | 13 +++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c index 31f878ad099d..3a3c9374794e 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c @@ -98,6 +98,8 @@ static void rcar_du_encoder_mode_set(struct drm_encoder *encoder, struct drm_connector_state *conn_state) { struct rcar_du_encoder *renc = to_rcar_encoder(encoder); + struct drm_display_info *info = &conn_state->connector->display_info; + enum rcar_lvds_mode mode; rcar_du_crtc_route_output(crtc_state->crtc, renc->output); @@ -111,6 +113,31 @@ static void rcar_du_encoder_mode_set(struct drm_encoder *encoder, } renc->connector = to_rcar_connector(conn_state->connector); + + if (!info->num_bus_formats || !info->bus_formats) { + dev_err(encoder->dev->dev, "no LVDS bus format reported\n"); + return; + } + + switch (info->bus_formats[0]) { + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: + case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: + mode = RCAR_LVDS_MODE_JEIDA; + break; + case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: + mode = RCAR_LVDS_MODE_VESA; + break; + default: + dev_err(encoder->dev->dev, + "unsupported LVDS bus format 0x%04x\n", + info->bus_formats[0]); + return; + } + + if (info->bus_flags & DRM_BUS_FLAG_DATA_LSB_TO_MSB) + mode |= RCAR_LVDS_MODE_MIRROR; + + rcar_du_lvdsenc_set_mode(renc->lvds, mode); } static const struct drm_encoder_helper_funcs encoder_helper_funcs = { diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c index e3a4985f6f3f..1661f6201210 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c @@ -31,6 +31,7 @@ struct rcar_du_lvdsenc { bool enabled; enum rcar_lvds_input input; + enum rcar_lvds_mode mode; }; static void rcar_lvds_write(struct rcar_du_lvdsenc *lvds, u32 reg, u32 data) @@ -61,7 +62,7 @@ static void rcar_du_lvdsenc_start_gen2(struct rcar_du_lvdsenc *lvds, /* Select the input, hardcode mode 0, enable LVDS operation and turn * bias circuitry on. */ - lvdcr0 = LVDCR0_BEN | LVDCR0_LVEN; + lvdcr0 = (lvds->mode << LVDCR0_LVMD_SHIFT) | LVDCR0_BEN | LVDCR0_LVEN; if (rcrtc->index == 2) lvdcr0 |= LVDCR0_DUSEL; rcar_lvds_write(lvds, LVDCR0, lvdcr0); @@ -114,7 +115,7 @@ static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds, * Turn the PLL on, set it to LVDS normal mode, wait for the startup * delay and turn the output on. */ - lvdcr0 = LVDCR0_PLLON; + lvdcr0 = (lvds->mode << LVDCR0_LVMD_SHIFT) | LVDCR0_PLLON; rcar_lvds_write(lvds, LVDCR0, lvdcr0); lvdcr0 |= LVDCR0_PWD; @@ -211,6 +212,12 @@ void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds, mode->clock = clamp(mode->clock, 25175, 148500); } +void rcar_du_lvdsenc_set_mode(struct rcar_du_lvdsenc *lvds, + enum rcar_lvds_mode mode) +{ + lvds->mode = mode; +} + static int rcar_du_lvdsenc_get_resources(struct rcar_du_lvdsenc *lvds, struct platform_device *pdev) { diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h index dfdba746edf4..7218ac89333e 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h @@ -26,8 +26,17 @@ enum rcar_lvds_input { RCAR_LVDS_INPUT_DU2, }; +/* Keep in sync with the LVDCR0.LVMD hardware register values. */ +enum rcar_lvds_mode { + RCAR_LVDS_MODE_JEIDA = 0, + RCAR_LVDS_MODE_MIRROR = 1, + RCAR_LVDS_MODE_VESA = 4, +}; + #if IS_ENABLED(CONFIG_DRM_RCAR_LVDS) int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu); +void rcar_du_lvdsenc_set_mode(struct rcar_du_lvdsenc *lvds, + enum rcar_lvds_mode mode); int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds, struct drm_crtc *crtc, bool enable); void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds, @@ -37,6 +46,10 @@ static inline int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu) { return 0; } +static inline void rcar_du_lvdsenc_set_mode(struct rcar_du_lvdsenc *lvds, + enum rcar_lvds_mode mode) +{ +} static inline int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds, struct drm_crtc *crtc, bool enable) { -- Regards, Laurent Pinchart From mboxrd@z Thu Jan 1 00:00:00 1970 From: Laurent Pinchart Subject: [PATCH v3 2/9] drm: rcar-du: Add support for LVDS mode selection Date: Mon, 6 Mar 2017 02:02:55 +0200 Message-ID: <20170306000302.14149-3-laurent.pinchart+renesas@ideasonboard.com> References: <20170306000302.14149-1-laurent.pinchart+renesas@ideasonboard.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from galahad.ideasonboard.com (galahad.ideasonboard.com [185.26.127.97]) by gabe.freedesktop.org (Postfix) with ESMTPS id C732F6E31D for ; Mon, 6 Mar 2017 00:02:31 +0000 (UTC) In-Reply-To: <20170306000302.14149-1-laurent.pinchart+renesas@ideasonboard.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: dri-devel@lists.freedesktop.org Cc: linux-renesas-soc@vger.kernel.org List-Id: dri-devel@lists.freedesktop.org UmV0cmlldmUgdGhlIExWRFMgbW9kZSBmcm9tIHRoZSBwYW5lbCBhbmQgY29uZmlndXJlIHRoZSBM VkRTIGVuY29kZXIKYWNjb3JkaW5nbHkuIExWRFMgbW9kZSBzZWxlY3Rpb24gaXMgc3RhdGljIGFz IExWRFMgcGFuZWxzIGNhbid0IGJlCmhvdC1wbHVnZ2VkIG9uIGFueSBvZiB0aGUgZGV2aWNlIHN1 cHBvcnRlZCBieSB0aGUgZHJpdmVyLiBTdXBwb3J0IGZvcgpkeW5hbWljIG1vZGUgc2VsZWN0aW9u IGNhbiBiZSBpbXBsZW1lbnRlZCBpbiB0aGUgZnV0dXJlIHdoZW4gbmVlZGVkLgoKU2lnbmVkLW9m Zi1ieTogTGF1cmVudCBQaW5jaGFydCA8bGF1cmVudC5waW5jaGFydCtyZW5lc2FzQGlkZWFzb25i b2FyZC5jb20+Ci0tLQpDaGFuZ2VzIHNpbmNlIHYyOgoKLSBSZWJhc2VkIG9uIHRvcCBvZiB0aGUg RFJNX0JVU19GTEFHX0RBVEFfTUlSUk9SIHJlbmFtZS4KLS0tCiBkcml2ZXJzL2dwdS9kcm0vcmNh ci1kdS9yY2FyX2R1X2VuY29kZXIuYyB8IDI3ICsrKysrKysrKysrKysrKysrKysrKysrKysrKwog ZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9sdmRzZW5jLmMgfCAxMSArKysrKysrKyst LQogZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9sdmRzZW5jLmggfCAxMyArKysrKysr KysrKysrCiAzIGZpbGVzIGNoYW5nZWQsIDQ5IGluc2VydGlvbnMoKyksIDIgZGVsZXRpb25zKC0p CgpkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9lbmNvZGVyLmMg Yi9kcml2ZXJzL2dwdS9kcm0vcmNhci1kdS9yY2FyX2R1X2VuY29kZXIuYwppbmRleCAzMWY4Nzhh ZDA5OWQuLjNhM2M5Mzc0Nzk0ZSAxMDA2NDQKLS0tIGEvZHJpdmVycy9ncHUvZHJtL3JjYXItZHUv cmNhcl9kdV9lbmNvZGVyLmMKKysrIGIvZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9l bmNvZGVyLmMKQEAgLTk4LDYgKzk4LDggQEAgc3RhdGljIHZvaWQgcmNhcl9kdV9lbmNvZGVyX21v ZGVfc2V0KHN0cnVjdCBkcm1fZW5jb2RlciAqZW5jb2RlciwKIAkJCQkgICAgIHN0cnVjdCBkcm1f Y29ubmVjdG9yX3N0YXRlICpjb25uX3N0YXRlKQogewogCXN0cnVjdCByY2FyX2R1X2VuY29kZXIg KnJlbmMgPSB0b19yY2FyX2VuY29kZXIoZW5jb2Rlcik7CisJc3RydWN0IGRybV9kaXNwbGF5X2lu Zm8gKmluZm8gPSAmY29ubl9zdGF0ZS0+Y29ubmVjdG9yLT5kaXNwbGF5X2luZm87CisJZW51bSBy Y2FyX2x2ZHNfbW9kZSBtb2RlOwogCiAJcmNhcl9kdV9jcnRjX3JvdXRlX291dHB1dChjcnRjX3N0 YXRlLT5jcnRjLCByZW5jLT5vdXRwdXQpOwogCkBAIC0xMTEsNiArMTEzLDMxIEBAIHN0YXRpYyB2 b2lkIHJjYXJfZHVfZW5jb2Rlcl9tb2RlX3NldChzdHJ1Y3QgZHJtX2VuY29kZXIgKmVuY29kZXIs CiAJfQogCiAJcmVuYy0+Y29ubmVjdG9yID0gdG9fcmNhcl9jb25uZWN0b3IoY29ubl9zdGF0ZS0+ Y29ubmVjdG9yKTsKKworCWlmICghaW5mby0+bnVtX2J1c19mb3JtYXRzIHx8ICFpbmZvLT5idXNf Zm9ybWF0cykgeworCQlkZXZfZXJyKGVuY29kZXItPmRldi0+ZGV2LCAibm8gTFZEUyBidXMgZm9y bWF0IHJlcG9ydGVkXG4iKTsKKwkJcmV0dXJuOworCX0KKworCXN3aXRjaCAoaW5mby0+YnVzX2Zv cm1hdHNbMF0pIHsKKwljYXNlIE1FRElBX0JVU19GTVRfUkdCNjY2XzFYN1gzX1NQV0c6CisJY2Fz ZSBNRURJQV9CVVNfRk1UX1JHQjg4OF8xWDdYNF9KRUlEQToKKwkJbW9kZSA9IFJDQVJfTFZEU19N T0RFX0pFSURBOworCQlicmVhazsKKwljYXNlIE1FRElBX0JVU19GTVRfUkdCODg4XzFYN1g0X1NQ V0c6CisJCW1vZGUgPSBSQ0FSX0xWRFNfTU9ERV9WRVNBOworCQlicmVhazsKKwlkZWZhdWx0Ogor CQlkZXZfZXJyKGVuY29kZXItPmRldi0+ZGV2LAorCQkJInVuc3VwcG9ydGVkIExWRFMgYnVzIGZv cm1hdCAweCUwNHhcbiIsCisJCQlpbmZvLT5idXNfZm9ybWF0c1swXSk7CisJCXJldHVybjsKKwl9 CisKKwlpZiAoaW5mby0+YnVzX2ZsYWdzICYgRFJNX0JVU19GTEFHX0RBVEFfTFNCX1RPX01TQikK KwkJbW9kZSB8PSBSQ0FSX0xWRFNfTU9ERV9NSVJST1I7CisKKwlyY2FyX2R1X2x2ZHNlbmNfc2V0 X21vZGUocmVuYy0+bHZkcywgbW9kZSk7CiB9CiAKIHN0YXRpYyBjb25zdCBzdHJ1Y3QgZHJtX2Vu Y29kZXJfaGVscGVyX2Z1bmNzIGVuY29kZXJfaGVscGVyX2Z1bmNzID0gewpkaWZmIC0tZ2l0IGEv ZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9sdmRzZW5jLmMgYi9kcml2ZXJzL2dwdS9k cm0vcmNhci1kdS9yY2FyX2R1X2x2ZHNlbmMuYwppbmRleCBlM2E0OTg1ZjZmM2YuLjE2NjFmNjIw MTIxMCAxMDA2NDQKLS0tIGEvZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9sdmRzZW5j LmMKKysrIGIvZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9sdmRzZW5jLmMKQEAgLTMx LDYgKzMxLDcgQEAgc3RydWN0IHJjYXJfZHVfbHZkc2VuYyB7CiAJYm9vbCBlbmFibGVkOwogCiAJ ZW51bSByY2FyX2x2ZHNfaW5wdXQgaW5wdXQ7CisJZW51bSByY2FyX2x2ZHNfbW9kZSBtb2RlOwog fTsKIAogc3RhdGljIHZvaWQgcmNhcl9sdmRzX3dyaXRlKHN0cnVjdCByY2FyX2R1X2x2ZHNlbmMg Kmx2ZHMsIHUzMiByZWcsIHUzMiBkYXRhKQpAQCAtNjEsNyArNjIsNyBAQCBzdGF0aWMgdm9pZCBy Y2FyX2R1X2x2ZHNlbmNfc3RhcnRfZ2VuMihzdHJ1Y3QgcmNhcl9kdV9sdmRzZW5jICpsdmRzLAog CS8qIFNlbGVjdCB0aGUgaW5wdXQsIGhhcmRjb2RlIG1vZGUgMCwgZW5hYmxlIExWRFMgb3BlcmF0 aW9uIGFuZCB0dXJuCiAJICogYmlhcyBjaXJjdWl0cnkgb24uCiAJICovCi0JbHZkY3IwID0gTFZE Q1IwX0JFTiB8IExWRENSMF9MVkVOOworCWx2ZGNyMCA9IChsdmRzLT5tb2RlIDw8IExWRENSMF9M Vk1EX1NISUZUKSB8IExWRENSMF9CRU4gfCBMVkRDUjBfTFZFTjsKIAlpZiAocmNydGMtPmluZGV4 ID09IDIpCiAJCWx2ZGNyMCB8PSBMVkRDUjBfRFVTRUw7CiAJcmNhcl9sdmRzX3dyaXRlKGx2ZHMs IExWRENSMCwgbHZkY3IwKTsKQEAgLTExNCw3ICsxMTUsNyBAQCBzdGF0aWMgdm9pZCByY2FyX2R1 X2x2ZHNlbmNfc3RhcnRfZ2VuMyhzdHJ1Y3QgcmNhcl9kdV9sdmRzZW5jICpsdmRzLAogCSAqIFR1 cm4gdGhlIFBMTCBvbiwgc2V0IGl0IHRvIExWRFMgbm9ybWFsIG1vZGUsIHdhaXQgZm9yIHRoZSBz dGFydHVwCiAJICogZGVsYXkgYW5kIHR1cm4gdGhlIG91dHB1dCBvbi4KIAkgKi8KLQlsdmRjcjAg PSBMVkRDUjBfUExMT047CisJbHZkY3IwID0gKGx2ZHMtPm1vZGUgPDwgTFZEQ1IwX0xWTURfU0hJ RlQpIHwgTFZEQ1IwX1BMTE9OOwogCXJjYXJfbHZkc193cml0ZShsdmRzLCBMVkRDUjAsIGx2ZGNy MCk7CiAKIAlsdmRjcjAgfD0gTFZEQ1IwX1BXRDsKQEAgLTIxMSw2ICsyMTIsMTIgQEAgdm9pZCBy Y2FyX2R1X2x2ZHNlbmNfYXRvbWljX2NoZWNrKHN0cnVjdCByY2FyX2R1X2x2ZHNlbmMgKmx2ZHMs CiAJCW1vZGUtPmNsb2NrID0gY2xhbXAobW9kZS0+Y2xvY2ssIDI1MTc1LCAxNDg1MDApOwogfQog Cit2b2lkIHJjYXJfZHVfbHZkc2VuY19zZXRfbW9kZShzdHJ1Y3QgcmNhcl9kdV9sdmRzZW5jICps dmRzLAorCQkJICAgICAgZW51bSByY2FyX2x2ZHNfbW9kZSBtb2RlKQoreworCWx2ZHMtPm1vZGUg PSBtb2RlOworfQorCiBzdGF0aWMgaW50IHJjYXJfZHVfbHZkc2VuY19nZXRfcmVzb3VyY2VzKHN0 cnVjdCByY2FyX2R1X2x2ZHNlbmMgKmx2ZHMsCiAJCQkJCSBzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNl ICpwZGV2KQogewpkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9s dmRzZW5jLmggYi9kcml2ZXJzL2dwdS9kcm0vcmNhci1kdS9yY2FyX2R1X2x2ZHNlbmMuaAppbmRl eCBkZmRiYTc0NmVkZjQuLjcyMThhYzg5MzMzZSAxMDA2NDQKLS0tIGEvZHJpdmVycy9ncHUvZHJt L3JjYXItZHUvcmNhcl9kdV9sdmRzZW5jLmgKKysrIGIvZHJpdmVycy9ncHUvZHJtL3JjYXItZHUv cmNhcl9kdV9sdmRzZW5jLmgKQEAgLTI2LDggKzI2LDE3IEBAIGVudW0gcmNhcl9sdmRzX2lucHV0 IHsKIAlSQ0FSX0xWRFNfSU5QVVRfRFUyLAogfTsKIAorLyogS2VlcCBpbiBzeW5jIHdpdGggdGhl IExWRENSMC5MVk1EIGhhcmR3YXJlIHJlZ2lzdGVyIHZhbHVlcy4gKi8KK2VudW0gcmNhcl9sdmRz X21vZGUgeworCVJDQVJfTFZEU19NT0RFX0pFSURBID0gMCwKKwlSQ0FSX0xWRFNfTU9ERV9NSVJS T1IgPSAxLAorCVJDQVJfTFZEU19NT0RFX1ZFU0EgPSA0LAorfTsKKwogI2lmIElTX0VOQUJMRUQo Q09ORklHX0RSTV9SQ0FSX0xWRFMpCiBpbnQgcmNhcl9kdV9sdmRzZW5jX2luaXQoc3RydWN0IHJj YXJfZHVfZGV2aWNlICpyY2R1KTsKK3ZvaWQgcmNhcl9kdV9sdmRzZW5jX3NldF9tb2RlKHN0cnVj dCByY2FyX2R1X2x2ZHNlbmMgKmx2ZHMsCisJCQkgICAgICBlbnVtIHJjYXJfbHZkc19tb2RlIG1v ZGUpOwogaW50IHJjYXJfZHVfbHZkc2VuY19lbmFibGUoc3RydWN0IHJjYXJfZHVfbHZkc2VuYyAq bHZkcywKIAkJCSAgIHN0cnVjdCBkcm1fY3J0YyAqY3J0YywgYm9vbCBlbmFibGUpOwogdm9pZCBy Y2FyX2R1X2x2ZHNlbmNfYXRvbWljX2NoZWNrKHN0cnVjdCByY2FyX2R1X2x2ZHNlbmMgKmx2ZHMs CkBAIC0zNyw2ICs0NiwxMCBAQCBzdGF0aWMgaW5saW5lIGludCByY2FyX2R1X2x2ZHNlbmNfaW5p dChzdHJ1Y3QgcmNhcl9kdV9kZXZpY2UgKnJjZHUpCiB7CiAJcmV0dXJuIDA7CiB9CitzdGF0aWMg aW5saW5lIHZvaWQgcmNhcl9kdV9sdmRzZW5jX3NldF9tb2RlKHN0cnVjdCByY2FyX2R1X2x2ZHNl bmMgKmx2ZHMsCisJCQkJCSAgICBlbnVtIHJjYXJfbHZkc19tb2RlIG1vZGUpCit7Cit9CiBzdGF0 aWMgaW5saW5lIGludCByY2FyX2R1X2x2ZHNlbmNfZW5hYmxlKHN0cnVjdCByY2FyX2R1X2x2ZHNl bmMgKmx2ZHMsCiAJCQkJCSBzdHJ1Y3QgZHJtX2NydGMgKmNydGMsIGJvb2wgZW5hYmxlKQogewot LSAKUmVnYXJkcywKCkxhdXJlbnQgUGluY2hhcnQKCl9fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fCmRyaS1kZXZlbCBtYWlsaW5nIGxpc3QKZHJpLWRldmVsQGxp c3RzLmZyZWVkZXNrdG9wLm9yZwpodHRwczovL2xpc3RzLmZyZWVkZXNrdG9wLm9yZy9tYWlsbWFu L2xpc3RpbmZvL2RyaS1kZXZlbAo=