Received: by 2002:a05:6358:11c7:b0:104:8066:f915 with SMTP id i7csp771994rwl; Fri, 31 Mar 2023 02:03:47 -0700 (PDT) X-Google-Smtp-Source: AKy350YM/8sYrTqYBfRDXZxBFxmc2LWNBHlfb1RfnvWWh4hCw2uhQ+SBxt7zgzVERIg7LCXm8FXZ X-Received: by 2002:a05:6402:5107:b0:502:ffd:74a0 with SMTP id m7-20020a056402510700b005020ffd74a0mr5524801edd.2.1680253427490; Fri, 31 Mar 2023 02:03:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680253427; cv=none; d=google.com; s=arc-20160816; b=RN+XMYGw/oAOYkwiOkaD2VCMb7yor1/YXIkiLBVrW71413YvcUeLkiG+culqGbiR88 TqYgCVVpT9+13tkTHKHi1XxlP/rbOfhkh1DjW1qH+3A85rGebmre/DfvS56TLgo5L0Td yn51R/swb0rCnH1JmPwAi9BZW9drdZcYlwQP5N5BqBhpn0YHNEZiC6P5cq+qLHPo1Saw xPqXIwUxcmX5BoXOXyrY3x2CX0fMBxKY0HLt9CeOzfhtpjsLlVfqZ5emiv6tFcyC5tAp z7Ty3h3r+wUinpQPP9jh8AzdTkHfUxuoOFFn8ZCcH9EiDSovfA38EEd2IqHs30phi8zW WJ4Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:in-reply-to :organization:references:cc:to:content-language:subject:reply-to :from:user-agent:mime-version:date:message-id:dkim-signature; bh=Ye0o0DOlmwExDTDHeZjZe7L/whuEGmKI0wj5yw1wRxo=; b=onZM5k+9WfdSw15//kthZ42z/nkd6GE7V5bJxOWcwW57EGeuRtzwOYdKNCX9DpEEu9 9d60EShv6pe2P3ulGMBGMGmEpu+bKlJMW5kIxQdzZRbqhIeC0vdMm8jRPfv2/0gSNBeH cHjEMxPp/MwUeYxRrOdL5Act5IeD1oBm4S4TOrToOdKVDhjuPHpA0R/bTOWTWZ6sspe5 cWjhBCpOzLra/E8s3Kkk5QShp0j1+z8xlhuqdm63OaPa4ELdkwb8650qgKFmXyaHaJXo gGUvHC/ftDzPtMvJeylrm1gFT//hlaErEFj8ESs3zxYiHno/lAACkgLR1rxeeNDEnJ5h /4Sg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=PFc7jF3I; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id jg29-20020a170907971d00b00947a3ecc3b7si1290903ejc.624.2023.03.31.02.03.17; Fri, 31 Mar 2023 02:03:47 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=PFc7jF3I; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231310AbjCaJAF (ORCPT + 99 others); Fri, 31 Mar 2023 05:00:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42174 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231537AbjCaJAC (ORCPT ); Fri, 31 Mar 2023 05:00:02 -0400 Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B6D81CA18 for ; Fri, 31 Mar 2023 01:59:58 -0700 (PDT) Received: by mail-wr1-x429.google.com with SMTP id l27so21663606wrb.2 for ; Fri, 31 Mar 2023 01:59:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1680253197; h=content-transfer-encoding:in-reply-to:organization:references:cc:to :content-language:subject:reply-to:from:user-agent:mime-version:date :message-id:from:to:cc:subject:date:message-id:reply-to; bh=Ye0o0DOlmwExDTDHeZjZe7L/whuEGmKI0wj5yw1wRxo=; b=PFc7jF3ItJ+FZRQN3LHZe0MawGiBP/Lg8vX5Ch4HlshzvoOfePQ6XRZ3aBsuxAn28m SRSgJM3MFuaMO89mmA6ZOeXGHZT0DoHu+qktfaA7Pq+TGdqjOFVM5GbVncoKkmNjcLN9 jmfvQZHE/teBTICIU+/A9A2hYqq31M5r7V9Cw2z9LzuKIg6eAdrodZ0KvP5eJs6Sct89 iZwO204UO2yhEgP2cNtNXDfmyzVGpHQKamm9qwxnqpgkWlMllLhSpvS/DtKFtdEoG4n6 jHa/N9ltuhEC0nj+IwyYCZctjLN4VB7XbJEk8qo8IWY0j/cq8CWtnI3mFQ09dqPiMWOn gk4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680253197; h=content-transfer-encoding:in-reply-to:organization:references:cc:to :content-language:subject:reply-to:from:user-agent:mime-version:date :message-id:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Ye0o0DOlmwExDTDHeZjZe7L/whuEGmKI0wj5yw1wRxo=; b=12jWgP57Jlreu/9RbMCn8OBIFrBiqNCqbArhP/4jQcoJqErrNUahcbnMvebiLKulqa qy48UjA2lEZmOh6xA8JP14V+r3GJXsR75ENmcFEEnh58eddW52wcvSuCN4oopHrnKNQk HoQnUn7Kq9bJ9o8OgrOkhU9Vt4NxTNwLMR62tnwJABpm3oULyi793IIdSHr9KyDQiBDJ 8NkBsy/t0dMAn/COrVCKiFR6bSuCfMaz3TsszcBDYgq0zZGhhmiK1rEAW8b4Pl0sVzu9 mFr7BokVxfyVDm+8onCHIz4SjqcHRmGPBh1AgBnBEaSvcxJ8S1u38D5NZLYNO2bHgxUs YPbQ== X-Gm-Message-State: AAQBX9f0aGBO1N3bB0EeWLZ/K9eu83T/ncShf3Idelsgm9HJkvveDDe/ RlR7zCoxXzClQrRfl/U3dvso2g== X-Received: by 2002:adf:ed0e:0:b0:2d1:86e6:bd6 with SMTP id a14-20020adfed0e000000b002d186e60bd6mr19853304wro.22.1680253197081; Fri, 31 Mar 2023 01:59:57 -0700 (PDT) Received: from ?IPV6:2a01:e0a:982:cbb0:74cb:1a96:c994:e7e0? ([2a01:e0a:982:cbb0:74cb:1a96:c994:e7e0]) by smtp.gmail.com with ESMTPSA id a15-20020a5d508f000000b002c707785da4sm1587034wrt.107.2023.03.31.01.59.56 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 31 Mar 2023 01:59:56 -0700 (PDT) Message-ID: Date: Fri, 31 Mar 2023 10:59:55 +0200 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.9.1 From: Neil Armstrong Reply-To: neil.armstrong@linaro.org Subject: Re: [PATCH v3 1/3] drm/bridge: tfp410: Support basic I2C interface Content-Language: en-US To: Jonathan Cormier , Andrzej Hajda , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , David Airlie , Daniel Vetter , Rob Herring , Krzysztof Kozlowski Cc: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Michael Williamson , Bob Duke References: <20230125-tfp410_i2c-v3-0-a85d5f0f50f1@criticallink.com> <20230125-tfp410_i2c-v3-1-a85d5f0f50f1@criticallink.com> Organization: Linaro Developer Services In-Reply-To: <20230125-tfp410_i2c-v3-1-a85d5f0f50f1@criticallink.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,NICE_REPLY_A,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 20/02/2023 23:10, Jonathan Cormier wrote: > From: Michael Williamson > > The TFP410 driver does not support I2C. As such, the device remains in > Power Down if the I2C is enabled by the bootstrap pins. > > Add basic support for the I2C interface, and provide support to take > the device out of power down when enabled. Also read the bootstrap mode > pins via the CTL_1_MODE register when using the I2C bus. > > Signed-off-by: Michael Williamson > Signed-off-by: Jonathan Cormier > --- > drivers/gpu/drm/bridge/ti-tfp410.c | 93 +++++++++++++++++++++++++++----------- > 1 file changed, 67 insertions(+), 26 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c > index b9635abbad16..bb3f8d0ff207 100644 > --- a/drivers/gpu/drm/bridge/ti-tfp410.c > +++ b/drivers/gpu/drm/bridge/ti-tfp410.c > @@ -6,6 +6,7 @@ > > #include > #include > +#include > #include > #include > #include > @@ -21,6 +22,20 @@ > > #define HOTPLUG_DEBOUNCE_MS 1100 > > +#define TFP410_REG_CTL_1_MODE 0x08 > +#define TFP410_BIT_PD BIT(0) > +#define TFP410_BIT_EDGE BIT(1) > +#define TFP410_BIT_BSEL BIT(2) > +#define TFP410_BIT_DSEL BIT(3) > + > +static const struct regmap_config tfp410_regmap_config = { > + .reg_bits = 8, > + .val_bits = 8, > + > + .max_register = 0xff, > + .cache_type = REGCACHE_NONE, > +}; > + > struct tfp410 { > struct drm_bridge bridge; > struct drm_connector connector; > @@ -33,6 +48,8 @@ struct tfp410 { > struct drm_bridge *next_bridge; > > struct device *dev; > + struct i2c_client *i2c; > + struct regmap *regmap; > }; > > static inline struct tfp410 * > @@ -183,6 +200,9 @@ static void tfp410_enable(struct drm_bridge *bridge) > { > struct tfp410 *dvi = drm_bridge_to_tfp410(bridge); > > + if (dvi->i2c) > + regmap_set_bits(dvi->regmap, TFP410_REG_CTL_1_MODE, TFP410_BIT_PD); > + > gpiod_set_value_cansleep(dvi->powerdown, 0); > } > > @@ -190,6 +210,9 @@ static void tfp410_disable(struct drm_bridge *bridge) > { > struct tfp410 *dvi = drm_bridge_to_tfp410(bridge); > > + if (dvi->i2c) > + regmap_clear_bits(dvi->regmap, TFP410_REG_CTL_1_MODE, TFP410_BIT_PD); > + > gpiod_set_value_cansleep(dvi->powerdown, 1); > } > > @@ -221,38 +244,48 @@ static const struct drm_bridge_timings tfp410_default_timings = { > .hold_time_ps = 1300, > }; > > -static int tfp410_parse_timings(struct tfp410 *dvi, bool i2c) > +static int tfp410_parse_timings(struct tfp410 *dvi) > { > struct drm_bridge_timings *timings = &dvi->timings; > struct device_node *ep; > u32 pclk_sample = 0; > u32 bus_width = 24; > u32 deskew = 0; > + unsigned int val = 0; > + int ret = 0; > > /* Start with defaults. */ > *timings = tfp410_default_timings; > > - if (i2c) > + if (dvi->i2c) { > /* > - * In I2C mode timings are configured through the I2C interface. > - * As the driver doesn't support I2C configuration yet, we just > - * go with the defaults (BSEL=1, DSEL=1, DKEN=0, EDGE=1). > + * For now, assume settings are latched from pins on reset / power up. > + * Should add options to optionally set them out of DT properties. > */ > - return 0; > - > - /* > - * In non-I2C mode, timings are configured through the BSEL, DSEL, DKEN > - * and EDGE pins. They are specified in DT through endpoint properties > - * and vendor-specific properties. > - */ > - ep = of_graph_get_endpoint_by_regs(dvi->dev->of_node, 0, 0); > - if (!ep) > - return -EINVAL; > - > - /* Get the sampling edge from the endpoint. */ > - of_property_read_u32(ep, "pclk-sample", &pclk_sample); > - of_property_read_u32(ep, "bus-width", &bus_width); > - of_node_put(ep); > + ret = regmap_read(dvi->regmap, TFP410_REG_CTL_1_MODE, &val); > + if (ret) { > + dev_err(dvi->dev, "Read failed on CTL_1_MODE\n"); > + return ret; > + } > + pclk_sample = (val & TFP410_BIT_EDGE) ? 1 : 0; > + bus_width = (val & TFP410_BIT_BSEL) ? 24 : 12; > + dev_dbg(dvi->dev, "(0x%02X) : detected %d bus width, %s edge sampling\n", > + val, bus_width, pclk_sample ? "positive" : "negative"); > + } else { > + /* > + * In non-I2C mode, timings are configured through the BSEL, DSEL, DKEN > + * and EDGE pins. They are specified in DT through endpoint properties > + * and vendor-specific properties. > + */ > + ep = of_graph_get_endpoint_by_regs(dvi->dev->of_node, 0, 0); > + if (!ep) > + return -EINVAL; > + > + /* Get the sampling edge from the endpoint. */ > + of_property_read_u32(ep, "pclk-sample", &pclk_sample); > + of_property_read_u32(ep, "bus-width", &bus_width); > + of_node_put(ep); > + } > > timings->input_bus_flags = DRM_BUS_FLAG_DE_HIGH; > > @@ -291,7 +324,7 @@ static int tfp410_parse_timings(struct tfp410 *dvi, bool i2c) > return 0; > } > > -static int tfp410_init(struct device *dev, bool i2c) > +static int tfp410_init(struct device *dev, struct i2c_client *i2c) > { > struct device_node *node; > struct tfp410 *dvi; > @@ -313,15 +346,24 @@ static int tfp410_init(struct device *dev, bool i2c) > dvi->bridge.of_node = dev->of_node; > dvi->bridge.timings = &dvi->timings; > dvi->bridge.type = DRM_MODE_CONNECTOR_DVID; > + dvi->i2c = i2c; > + > + if (i2c) { > + dvi->regmap = devm_regmap_init_i2c(i2c, &tfp410_regmap_config); > + if (IS_ERR(dvi->regmap)) > + return PTR_ERR(dvi->regmap); > + } > > - ret = tfp410_parse_timings(dvi, i2c); > + ret = tfp410_parse_timings(dvi); > if (ret) > return ret; > > /* Get the next bridge, connected to port@1. */ > node = of_graph_get_remote_node(dev->of_node, 1, -1); > - if (!node) > + if (!node) { > + dev_err(dev, "Could not find remote node\n"); > return -ENODEV; > + } > > dvi->next_bridge = of_drm_find_bridge(node); > of_node_put(node); > @@ -352,7 +394,7 @@ static void tfp410_fini(struct device *dev) > > static int tfp410_probe(struct platform_device *pdev) > { > - return tfp410_init(&pdev->dev, false); > + return tfp410_init(&pdev->dev, NULL); > } > > static int tfp410_remove(struct platform_device *pdev) > @@ -378,7 +420,6 @@ static struct platform_driver tfp410_platform_driver = { > }; > > #if IS_ENABLED(CONFIG_I2C) > -/* There is currently no i2c functionality. */ > static int tfp410_i2c_probe(struct i2c_client *client, > const struct i2c_device_id *id) > { > @@ -391,7 +432,7 @@ static int tfp410_i2c_probe(struct i2c_client *client, > return -ENXIO; > } > > - return tfp410_init(&client->dev, true); > + return tfp410_init(&client->dev, client); > } > > static void tfp410_i2c_remove(struct i2c_client *client) > Reviewed-by: Neil Armstrong