From patchwork Tue Jun 27 17:56:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 13294868 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 134F7EB64D9 for ; Tue, 27 Jun 2023 17:57:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231855AbjF0R5k (ORCPT ); Tue, 27 Jun 2023 13:57:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37402 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230361AbjF0R5i (ORCPT ); Tue, 27 Jun 2023 13:57:38 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C881C296B for ; Tue, 27 Jun 2023 10:56:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1687888610; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=R0U8uQhbtG16k9BC3X+eFDuoEN8n7CYMNO+M8lwvbi0=; b=N50N82kje9SxsQvRb31bkBHt5m/cak2BYXCF3WQ0r+/R7CkZ3j1vusBe7nFNelCn2Ev0oj Ywh+NfV0O8M8oQ0ddOmsZBob8R98QmEwQS5A7k14EdSt1BYdJ9KrAl6gp8fo2RPmRbbY7l kdm/3ATQ8Z/FBZ60Mf1vVKL+BjmwPXs= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-364-WU1u5ucgMSuV_zw8Zoy9jQ-1; Tue, 27 Jun 2023 13:56:47 -0400 X-MC-Unique: WU1u5ucgMSuV_zw8Zoy9jQ-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id BDEDB92E4C1; Tue, 27 Jun 2023 17:56:46 +0000 (UTC) Received: from shalem.redhat.com (unknown [10.39.194.24]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6D98A200A3AD; Tue, 27 Jun 2023 17:56:45 +0000 (UTC) From: Hans de Goede To: Sakari Ailus , Laurent Pinchart , Daniel Scally Cc: Hans de Goede , Mauro Carvalho Chehab , Andy Shevchenko , Kate Hsuan , Hao Yao , Bingbu Cao , linux-media@vger.kernel.org Subject: [PATCH 01/12] media: ipu3-cio2: Do not use on stack memory for software_node.name field Date: Tue, 27 Jun 2023 19:56:31 +0200 Message-ID: <20230627175643.114778-2-hdegoede@redhat.com> In-Reply-To: <20230627175643.114778-1-hdegoede@redhat.com> References: <20230627175643.114778-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Commit 567f97bd381f ("media: ipu3-cio2: support multiple sensors and VCMs with same HID") introduced an on stack vcm_name and then uses this for the name field of the software_node struct used for the vcm. But the software_node struct is much longer lived then the current stack-frame, so this is no good. Instead extend the cio2_node_names struct with an extra field to store the vcm software_node name and use that. Note this also changes the length of the allocated buffer from ACPI_ID_LEN + 4 to 16. the name is filled with "-%u" where cio2_vcm_types[x] is not an ACPI_ID. The maximum length of the strings in the cio2_vcm_types[] array is 11 + 5 bytes for "-255\0" means 16 bytes are needed in the worst case scenario. Fixes: 567f97bd381f ("media: ipu3-cio2: support multiple sensors and VCMs with same HID") Cc: Bingbu Cao Signed-off-by: Hans de Goede --- drivers/media/pci/intel/ipu3/cio2-bridge.c | 7 +++---- drivers/media/pci/intel/ipu3/cio2-bridge.h | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index 3c2accfe5455..dab5395ccc84 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -220,7 +220,6 @@ static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge, struct cio2_sensor *sensor) { struct software_node *nodes = sensor->swnodes; - char vcm_name[ACPI_ID_LEN + 4]; cio2_bridge_init_swnode_names(sensor); @@ -240,10 +239,10 @@ static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge, sensor->cio2_properties); if (sensor->ssdb.vcmtype) { /* append ssdb.link to distinguish VCM nodes with same HID */ - snprintf(vcm_name, sizeof(vcm_name), "%s-%u", - cio2_vcm_types[sensor->ssdb.vcmtype - 1], + snprintf(sensor->node_names.vcm, sizeof(sensor->node_names.vcm), + "%s-%u", cio2_vcm_types[sensor->ssdb.vcmtype - 1], sensor->ssdb.link); - nodes[SWNODE_VCM] = NODE_VCM(vcm_name); + nodes[SWNODE_VCM] = NODE_VCM(sensor->node_names.vcm); } cio2_bridge_init_swnode_group(sensor); diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h index b76ed8a641e2..a824b96bcdf2 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.h +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h @@ -104,6 +104,7 @@ struct cio2_node_names { char port[7]; char endpoint[11]; char remote_port[7]; + char vcm[16]; }; struct cio2_sensor_config { From patchwork Tue Jun 27 17:56:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 13294869 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9CA36EB64DC for ; Tue, 27 Jun 2023 17:57:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231909AbjF0R5v (ORCPT ); Tue, 27 Jun 2023 13:57:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37374 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231859AbjF0R5n (ORCPT ); Tue, 27 Jun 2023 13:57:43 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C8B252D4F for ; Tue, 27 Jun 2023 10:56:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1687888610; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=w8MUS/JF8mAAIA1wCYsaqakNYwVwRSrtgG+mkyN+AN8=; b=csgb1aPYBP8vH49iRy/tCbVWItcxeW6dx3JIdYijb8pCVrwJ8erARAdzGVJDZP0CUiTJTs eiOCqoTmlqvaaDSdUKztWvLYBb3L4ojilr72llxEr6Le0MyVk5O/iGBtuMXyzAh0sj747J QBwRtquW9nVDrYRtJXjc2oKn3T9eEDs= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-618-4bdiVO-hN4ulDOOFVJgbRw-1; Tue, 27 Jun 2023 13:56:48 -0400 X-MC-Unique: 4bdiVO-hN4ulDOOFVJgbRw-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 4FAB1280BC4C; Tue, 27 Jun 2023 17:56:48 +0000 (UTC) Received: from shalem.redhat.com (unknown [10.39.194.24]) by smtp.corp.redhat.com (Postfix) with ESMTP id F203E200A3AD; Tue, 27 Jun 2023 17:56:46 +0000 (UTC) From: Hans de Goede To: Sakari Ailus , Laurent Pinchart , Daniel Scally Cc: Hans de Goede , Mauro Carvalho Chehab , Andy Shevchenko , Kate Hsuan , Hao Yao , Bingbu Cao , linux-media@vger.kernel.org Subject: [PATCH 02/12] media: ipu3-cio2: Move initialization of node_names.vcm to cio2_bridge_init_swnode_names() Date: Tue, 27 Jun 2023 19:56:32 +0200 Message-ID: <20230627175643.114778-3-hdegoede@redhat.com> In-Reply-To: <20230627175643.114778-1-hdegoede@redhat.com> References: <20230627175643.114778-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Move initialization of node_names.vcm to cio2_bridge_init_swnode_names() where it belongs. And make the initialization of nodes[SWNODE_VCM] unconditional, cio2_bridge_init_swnode_group() takes care of not registering it when there is no VCM. Signed-off-by: Hans de Goede --- drivers/media/pci/intel/ipu3/cio2-bridge.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index dab5395ccc84..0f7adca9d6f9 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -201,6 +201,12 @@ static void cio2_bridge_init_swnode_names(struct cio2_sensor *sensor) snprintf(sensor->node_names.endpoint, sizeof(sensor->node_names.endpoint), SWNODE_GRAPH_ENDPOINT_NAME_FMT, 0); /* And endpoint 0 */ + if (sensor->ssdb.vcmtype) { + /* append ssdb.link to distinguish nodes with same model VCM */ + snprintf(sensor->node_names.vcm, sizeof(sensor->node_names.vcm), + "%s-%u", cio2_vcm_types[sensor->ssdb.vcmtype - 1], + sensor->ssdb.link); + } } static void cio2_bridge_init_swnode_group(struct cio2_sensor *sensor) @@ -237,13 +243,7 @@ static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge, sensor->node_names.endpoint, &nodes[SWNODE_CIO2_PORT], sensor->cio2_properties); - if (sensor->ssdb.vcmtype) { - /* append ssdb.link to distinguish VCM nodes with same HID */ - snprintf(sensor->node_names.vcm, sizeof(sensor->node_names.vcm), - "%s-%u", cio2_vcm_types[sensor->ssdb.vcmtype - 1], - sensor->ssdb.link); - nodes[SWNODE_VCM] = NODE_VCM(sensor->node_names.vcm); - } + nodes[SWNODE_VCM] = NODE_VCM(sensor->node_names.vcm); cio2_bridge_init_swnode_group(sensor); } From patchwork Tue Jun 27 17:56:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 13294873 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3EAB3EB64DC for ; Tue, 27 Jun 2023 17:58:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231896AbjF0R57 (ORCPT ); Tue, 27 Jun 2023 13:57:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37532 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231852AbjF0R5q (ORCPT ); Tue, 27 Jun 2023 13:57:46 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 971BF2D7D for ; Tue, 27 Jun 2023 10:56:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1687888613; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=gKtDMJU4mEJurNtFzATwewadf+bZ067mPE4miPWSVN4=; b=T9kVtpDTSlU8uHU3IW4NxaC0Et8Py5yrnTjeikXbgBW2HGWno+icQzcUPRCaABWuR7cJ4P S7xF/pxr0EakxGTHsFOi6dM8ie9APoirKs6cICcUOgfCL620S5Px+WkPffqZB+cHfOsIZg +4FSk76PNHjdAmrFfUYO+XNQNEst/2U= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-62-LLMfnjhqNHOsP91LCCU6Tw-1; Tue, 27 Jun 2023 13:56:50 -0400 X-MC-Unique: LLMfnjhqNHOsP91LCCU6Tw-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id D29243C0FCA0; Tue, 27 Jun 2023 17:56:49 +0000 (UTC) Received: from shalem.redhat.com (unknown [10.39.194.24]) by smtp.corp.redhat.com (Postfix) with ESMTP id 84831200B677; Tue, 27 Jun 2023 17:56:48 +0000 (UTC) From: Hans de Goede To: Sakari Ailus , Laurent Pinchart , Daniel Scally Cc: Hans de Goede , Mauro Carvalho Chehab , Andy Shevchenko , Kate Hsuan , Hao Yao , Bingbu Cao , linux-media@vger.kernel.org Subject: [PATCH 03/12] media: ipu3-cio2: Make cio2_bridge_init() take a regular struct device as argument Date: Tue, 27 Jun 2023 19:56:33 +0200 Message-ID: <20230627175643.114778-4-hdegoede@redhat.com> In-Reply-To: <20230627175643.114778-1-hdegoede@redhat.com> References: <20230627175643.114778-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Make cio2_bridge_init() take a regular struct device, rather then a pci_dev as argument. This is a preparation patch for making the cio2-bridge code more generic so that it can be shared with the atomisp driver. Signed-off-by: Hans de Goede --- drivers/media/pci/intel/ipu3/cio2-bridge.c | 16 +++++++--------- drivers/media/pci/intel/ipu3/ipu3-cio2-main.c | 2 +- drivers/media/pci/intel/ipu3/ipu3-cio2.h | 4 ++-- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index 0f7adca9d6f9..72a28844dfdb 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include @@ -288,7 +287,7 @@ static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge) static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, struct cio2_bridge *bridge, - struct pci_dev *cio2) + struct device *dev) { struct fwnode_handle *fwnode, *primary; struct cio2_sensor *sensor; @@ -302,7 +301,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, if (bridge->n_sensors >= CIO2_NUM_PORTS) { acpi_dev_put(adev); - dev_err(&cio2->dev, "Exceeded available CIO2 ports\n"); + dev_err(dev, "Exceeded available CIO2 ports\n"); return -EINVAL; } @@ -357,7 +356,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, cio2_bridge_instantiate_vcm_i2c_client(sensor); - dev_info(&cio2->dev, "Found supported sensor %s\n", + dev_info(dev, "Found supported sensor %s\n", acpi_dev_name(adev)); bridge->n_sensors++; @@ -375,7 +374,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, } static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge, - struct pci_dev *cio2) + struct device *dev) { unsigned int i; int ret; @@ -384,7 +383,7 @@ static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge, const struct cio2_sensor_config *cfg = &cio2_supported_sensors[i]; - ret = cio2_bridge_connect_sensor(cfg, bridge, cio2); + ret = cio2_bridge_connect_sensor(cfg, bridge, dev); if (ret) goto err_unregister_sensors; } @@ -430,9 +429,8 @@ static int cio2_bridge_sensors_are_ready(void) return ready; } -int cio2_bridge_init(struct pci_dev *cio2) +int cio2_bridge_init(struct device *dev) { - struct device *dev = &cio2->dev; struct fwnode_handle *fwnode; struct cio2_bridge *bridge; unsigned int i; @@ -465,7 +463,7 @@ int cio2_bridge_init(struct pci_dev *cio2) for (i = 0; i < CIO2_MAX_LANES; i++) bridge->data_lanes[i] = i + 1; - ret = cio2_bridge_connect_sensors(bridge, cio2); + ret = cio2_bridge_connect_sensors(bridge, dev); if (ret || bridge->n_sensors == 0) goto err_unregister_cio2; diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c index 34984a7474ed..afc3255b5eb8 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c @@ -1724,7 +1724,7 @@ static int cio2_pci_probe(struct pci_dev *pci_dev, return -EINVAL; } - r = cio2_bridge_init(pci_dev); + r = cio2_bridge_init(dev); if (r) return r; } diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.h b/drivers/media/pci/intel/ipu3/ipu3-cio2.h index 3a1f394e05aa..7ff7915f9823 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.h +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.h @@ -460,9 +460,9 @@ static inline struct cio2_queue *vb2q_to_cio2_queue(struct vb2_queue *vq) } #if IS_ENABLED(CONFIG_CIO2_BRIDGE) -int cio2_bridge_init(struct pci_dev *cio2); +int cio2_bridge_init(struct device *dev); #else -static inline int cio2_bridge_init(struct pci_dev *cio2) { return 0; } +static inline int cio2_bridge_init(struct device *dev) { return 0; } #endif #endif From patchwork Tue Jun 27 17:56:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 13294870 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2D7BDEB64D9 for ; Tue, 27 Jun 2023 17:57:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231882AbjF0R5y (ORCPT ); Tue, 27 Jun 2023 13:57:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37392 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231879AbjF0R5p (ORCPT ); Tue, 27 Jun 2023 13:57:45 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4EC83297C for ; Tue, 27 Jun 2023 10:56:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1687888615; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=IXspoUMbXahzIwGsmqD0Xy6ILU3RyqBjkkqTnQxjZu4=; b=RzfkTDDELg8I9Vy4SNF/vnE/BjUXt86zx577qBpO6SvYaBqop0ITZjn61fX21JYgryhj9i 6FCSYZQdN+uVL+gPNXYBeqtYiZE49Yf4wxom81oYydq1/gmX0TKzOe27YlAPorhHj8EI3/ kOWq+Ec1J9zN5C31NrI2WnZRwPT2VNw= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-118-AClckXdLN6iCSoHSBqW9eQ-1; Tue, 27 Jun 2023 13:56:52 -0400 X-MC-Unique: AClckXdLN6iCSoHSBqW9eQ-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 610E1280BC51; Tue, 27 Jun 2023 17:56:51 +0000 (UTC) Received: from shalem.redhat.com (unknown [10.39.194.24]) by smtp.corp.redhat.com (Postfix) with ESMTP id 125D3200A3AD; Tue, 27 Jun 2023 17:56:49 +0000 (UTC) From: Hans de Goede To: Sakari Ailus , Laurent Pinchart , Daniel Scally Cc: Hans de Goede , Mauro Carvalho Chehab , Andy Shevchenko , Kate Hsuan , Hao Yao , Bingbu Cao , linux-media@vger.kernel.org Subject: [PATCH 04/12] media: ipu3-cio2: Store dev pointer in struct cio2_bridge Date: Tue, 27 Jun 2023 19:56:34 +0200 Message-ID: <20230627175643.114778-5-hdegoede@redhat.com> In-Reply-To: <20230627175643.114778-1-hdegoede@redhat.com> References: <20230627175643.114778-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Store the dev pointer in struct cio2_bridge instead of passing it around 3 levels deep. This takes up slightly more memory but further patches in this series add more data which needs to be passed around making passing everything as arguments cumbersome and those further patches also add data to struct cio2_bridge. To be consistent with these upcoming patches also add the dev pointer to struct cio2_bridge. Signed-off-by: Hans de Goede --- drivers/media/pci/intel/ipu3/cio2-bridge.c | 15 +++++++-------- drivers/media/pci/intel/ipu3/cio2-bridge.h | 1 + 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index 72a28844dfdb..746c1dda31d1 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -286,8 +286,7 @@ static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge) } static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, - struct cio2_bridge *bridge, - struct device *dev) + struct cio2_bridge *bridge) { struct fwnode_handle *fwnode, *primary; struct cio2_sensor *sensor; @@ -301,7 +300,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, if (bridge->n_sensors >= CIO2_NUM_PORTS) { acpi_dev_put(adev); - dev_err(dev, "Exceeded available CIO2 ports\n"); + dev_err(bridge->dev, "Exceeded available CIO2 ports\n"); return -EINVAL; } @@ -356,7 +355,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, cio2_bridge_instantiate_vcm_i2c_client(sensor); - dev_info(dev, "Found supported sensor %s\n", + dev_info(bridge->dev, "Found supported sensor %s\n", acpi_dev_name(adev)); bridge->n_sensors++; @@ -373,8 +372,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, return ret; } -static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge, - struct device *dev) +static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge) { unsigned int i; int ret; @@ -383,7 +381,7 @@ static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge, const struct cio2_sensor_config *cfg = &cio2_supported_sensors[i]; - ret = cio2_bridge_connect_sensor(cfg, bridge, dev); + ret = cio2_bridge_connect_sensor(cfg, bridge); if (ret) goto err_unregister_sensors; } @@ -446,6 +444,7 @@ int cio2_bridge_init(struct device *dev) strscpy(bridge->cio2_node_name, CIO2_HID, sizeof(bridge->cio2_node_name)); bridge->cio2_hid_node.name = bridge->cio2_node_name; + bridge->dev = dev; ret = software_node_register(&bridge->cio2_hid_node); if (ret < 0) { @@ -463,7 +462,7 @@ int cio2_bridge_init(struct device *dev) for (i = 0; i < CIO2_MAX_LANES; i++) bridge->data_lanes[i] = i + 1; - ret = cio2_bridge_connect_sensors(bridge, dev); + ret = cio2_bridge_connect_sensors(bridge); if (ret || bridge->n_sensors == 0) goto err_unregister_cio2; diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h index a824b96bcdf2..8045ceab899b 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.h +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h @@ -137,6 +137,7 @@ struct cio2_sensor { }; struct cio2_bridge { + struct device *dev; char cio2_node_name[ACPI_ID_LEN]; struct software_node cio2_hid_node; u32 data_lanes[4]; From patchwork Tue Jun 27 17:56:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 13294871 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3201CEB64DD for ; Tue, 27 Jun 2023 17:57:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231879AbjF0R5z (ORCPT ); Tue, 27 Jun 2023 13:57:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37396 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231886AbjF0R5p (ORCPT ); Tue, 27 Jun 2023 13:57:45 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2C98E30D8 for ; Tue, 27 Jun 2023 10:56:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1687888616; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PmJGJf7PHFMYCPKvlc6eoiKx4hcI9rJSnVS9cs6J5XM=; b=ALu1Lvv+68u0YqatBX3+K6mUMXMXvB2ES/+Z+VqVOskhTqDw+1u6dXS50rc1PK5IR5uUz+ uZlTzT6v157kvXbTRc+k+lgLSuoS/AOEDK/000uB2RE6593BKt2frXX827HIPG8zLd74kr OoSrkZEU2fJxENovhXX5U7UDZOZihMo= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-453-wbT-lN8zNemno8N2ZqNTyQ-1; Tue, 27 Jun 2023 13:56:53 -0400 X-MC-Unique: wbT-lN8zNemno8N2ZqNTyQ-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E87A61C08963; Tue, 27 Jun 2023 17:56:52 +0000 (UTC) Received: from shalem.redhat.com (unknown [10.39.194.24]) by smtp.corp.redhat.com (Postfix) with ESMTP id 94506200B677; Tue, 27 Jun 2023 17:56:51 +0000 (UTC) From: Hans de Goede To: Sakari Ailus , Laurent Pinchart , Daniel Scally Cc: Hans de Goede , Mauro Carvalho Chehab , Andy Shevchenko , Kate Hsuan , Hao Yao , Bingbu Cao , linux-media@vger.kernel.org Subject: [PATCH 05/12] media: ipu3-cio2: Only keep PLD around while parsing Date: Tue, 27 Jun 2023 19:56:35 +0200 Message-ID: <20230627175643.114778-6-hdegoede@redhat.com> In-Reply-To: <20230627175643.114778-1-hdegoede@redhat.com> References: <20230627175643.114778-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org There is no need to keep a reference to the PLD struct around, it is only used once the get the sensor orientation. Rename cio2_bridge_parse_orientation() to cio2_bridge_get_orientation() and make it also get + put the PLD. This is a preparation patch for making the cio2-bridge code more generic so that it can be shared with the atomisp driver. Signed-off-by: Hans de Goede --- drivers/media/pci/intel/ipu3/cio2-bridge.c | 51 ++++++++++++---------- drivers/media/pci/intel/ipu3/cio2-bridge.h | 2 +- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index 746c1dda31d1..741ef54f0d65 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -112,23 +112,40 @@ static u32 cio2_bridge_parse_rotation(struct cio2_sensor *sensor) } } -static enum v4l2_fwnode_orientation cio2_bridge_parse_orientation(struct cio2_sensor *sensor) +static enum v4l2_fwnode_orientation +cio2_bridge_get_orientation(struct acpi_device *adev) { - switch (sensor->pld->panel) { + enum v4l2_fwnode_orientation orientation; + struct acpi_pld_info *pld; + acpi_status status; + + status = acpi_get_physical_device_location(adev->handle, &pld); + if (ACPI_FAILURE(status)) { + dev_warn(&adev->dev, "_PLD call failed using unknown orientation\n"); + return V4L2_FWNODE_ORIENTATION_EXTERNAL; + } + + switch (pld->panel) { case ACPI_PLD_PANEL_FRONT: - return V4L2_FWNODE_ORIENTATION_FRONT; + orientation = V4L2_FWNODE_ORIENTATION_FRONT; + break; case ACPI_PLD_PANEL_BACK: - return V4L2_FWNODE_ORIENTATION_BACK; + orientation = V4L2_FWNODE_ORIENTATION_BACK; + break; case ACPI_PLD_PANEL_TOP: case ACPI_PLD_PANEL_LEFT: case ACPI_PLD_PANEL_RIGHT: case ACPI_PLD_PANEL_UNKNOWN: - return V4L2_FWNODE_ORIENTATION_EXTERNAL; + orientation = V4L2_FWNODE_ORIENTATION_EXTERNAL; + break; default: - dev_warn(&sensor->adev->dev, "Unknown _PLD panel value %d\n", - sensor->pld->panel); - return V4L2_FWNODE_ORIENTATION_EXTERNAL; + dev_warn(&adev->dev, "Unknown _PLD panel val %d\n", pld->panel); + orientation = V4L2_FWNODE_ORIENTATION_EXTERNAL; + break; } + + ACPI_FREE(pld); + return orientation; } static void cio2_bridge_create_fwnode_properties( @@ -137,10 +154,8 @@ static void cio2_bridge_create_fwnode_properties( const struct cio2_sensor_config *cfg) { u32 rotation; - enum v4l2_fwnode_orientation orientation; rotation = cio2_bridge_parse_rotation(sensor); - orientation = cio2_bridge_parse_orientation(sensor); sensor->prop_names = prop_names; @@ -155,7 +170,7 @@ static void cio2_bridge_create_fwnode_properties( rotation); sensor->dev_properties[2] = PROPERTY_ENTRY_U32( sensor->prop_names.orientation, - orientation); + sensor->orientation); if (sensor->ssdb.vcmtype) { sensor->vcm_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_VCM]); @@ -279,7 +294,6 @@ static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge) for (i = 0; i < bridge->n_sensors; i++) { sensor = &bridge->sensors[i]; software_node_unregister_node_group(sensor->group); - ACPI_FREE(sensor->pld); acpi_dev_put(sensor->adev); i2c_unregister_device(sensor->vcm_i2c_client); } @@ -291,7 +305,6 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, struct fwnode_handle *fwnode, *primary; struct cio2_sensor *sensor; struct acpi_device *adev; - acpi_status status; int ret; for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { @@ -321,17 +334,13 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, sensor->ssdb.vcmtype = 0; } - status = acpi_get_physical_device_location(adev->handle, &sensor->pld); - if (ACPI_FAILURE(status)) { - ret = -ENODEV; - goto err_put_adev; - } + sensor->orientation = cio2_bridge_get_orientation(adev); if (sensor->ssdb.lanes > CIO2_MAX_LANES) { dev_err(&adev->dev, "Number of lanes in SSDB is invalid\n"); ret = -EINVAL; - goto err_free_pld; + goto err_put_adev; } cio2_bridge_create_fwnode_properties(sensor, bridge, cfg); @@ -339,7 +348,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, ret = software_node_register_node_group(sensor->group); if (ret) - goto err_free_pld; + goto err_put_adev; fwnode = software_node_fwnode(&sensor->swnodes[ SWNODE_SENSOR_HID]); @@ -365,8 +374,6 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, err_free_swnodes: software_node_unregister_node_group(sensor->group); -err_free_pld: - ACPI_FREE(sensor->pld); err_put_adev: acpi_dev_put(adev); return ret; diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h index 8045ceab899b..e42c5c3cf856 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.h +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h @@ -125,7 +125,7 @@ struct cio2_sensor { struct cio2_node_names node_names; struct cio2_sensor_ssdb ssdb; - struct acpi_pld_info *pld; + enum v4l2_fwnode_orientation orientation; struct cio2_property_names prop_names; struct property_entry ep_properties[5]; From patchwork Tue Jun 27 17:56:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 13294874 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 05B5FEB64D9 for ; Tue, 27 Jun 2023 17:58:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229861AbjF0R6C (ORCPT ); Tue, 27 Jun 2023 13:58:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37718 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231890AbjF0R57 (ORCPT ); Tue, 27 Jun 2023 13:57:59 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8DF2F30EE for ; Tue, 27 Jun 2023 10:56:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1687888618; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=87bfuPHXZ79fWnXMdkGohubTyPN+ikZ3NxNN00IHwk0=; b=ErHS6ZckibUyaxf7mRSX6CYT8xRRsp6w3FCOOWV+VVvoDBEjeel5OtPp5ltPl7TP+IO2U5 7yObPRxhAx27Q9Sb5ngeQX91hl96cqTqP0PHoXm/VpXPFVa21BzF5sLyaScX4C9AL54Hz/ 75iANpmVTcUQ1PqYoQCKpChFtnV4adY= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-675-aUtsP1BZPR-d9CvVEBLtug-1; Tue, 27 Jun 2023 13:56:55 -0400 X-MC-Unique: aUtsP1BZPR-d9CvVEBLtug-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 79DE580027F; Tue, 27 Jun 2023 17:56:54 +0000 (UTC) Received: from shalem.redhat.com (unknown [10.39.194.24]) by smtp.corp.redhat.com (Postfix) with ESMTP id 28DD7200A3AD; Tue, 27 Jun 2023 17:56:53 +0000 (UTC) From: Hans de Goede To: Sakari Ailus , Laurent Pinchart , Daniel Scally Cc: Hans de Goede , Mauro Carvalho Chehab , Andy Shevchenko , Kate Hsuan , Hao Yao , Bingbu Cao , linux-media@vger.kernel.org Subject: [PATCH 06/12] media: ipu3-cio2: Add a cio2_bridge_parse_sensor_fwnode() helper function Date: Tue, 27 Jun 2023 19:56:36 +0200 Message-ID: <20230627175643.114778-7-hdegoede@redhat.com> In-Reply-To: <20230627175643.114778-1-hdegoede@redhat.com> References: <20230627175643.114778-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org The code to go from ACPI sensor info to a fwnode-tree with connector nodes and endpoint properties is 99% the same for the atomisp2 and the IPU3. The main difference is that atomisp2 devices do not have a SSDB table with various info. Abstract out the parsing of the sensor's ACPI fwnode into a helper function and store the parsed results, rather then the raw SSDB in struct cio2_sensor. This is a preparation patch for making the cio2-bridge code more generic so that it can be shared with the atomisp driver. Signed-off-by: Hans de Goede --- drivers/media/pci/intel/ipu3/cio2-bridge.c | 94 ++++++++++++---------- drivers/media/pci/intel/ipu3/cio2-bridge.h | 6 +- 2 files changed, 56 insertions(+), 44 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index 741ef54f0d65..b189c2adf858 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -97,17 +97,18 @@ static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id, return ret; } -static u32 cio2_bridge_parse_rotation(struct cio2_sensor *sensor) +static u32 cio2_bridge_parse_rotation(struct acpi_device *adev, + struct cio2_sensor_ssdb *ssdb) { - switch (sensor->ssdb.degree) { + switch (ssdb->degree) { case CIO2_SENSOR_ROTATION_NORMAL: return 0; case CIO2_SENSOR_ROTATION_INVERTED: return 180; default: - dev_warn(&sensor->adev->dev, + dev_warn(&adev->dev, "Unknown rotation %d. Assume 0 degree rotation\n", - sensor->ssdb.degree); + ssdb->degree); return 0; } } @@ -148,15 +149,43 @@ cio2_bridge_get_orientation(struct acpi_device *adev) return orientation; } +static int cio2_bridge_parse_sensor_fwnode(struct acpi_device *adev, + struct cio2_sensor *sensor) +{ + struct cio2_sensor_ssdb ssdb = {}; + int ret; + + ret = cio2_bridge_read_acpi_buffer(adev, "SSDB", &ssdb, sizeof(ssdb)); + if (ret) + return ret; + + if (ssdb.vcmtype > ARRAY_SIZE(cio2_vcm_types)) { + dev_warn(&adev->dev, "Unknown VCM type %d\n", ssdb.vcmtype); + ssdb.vcmtype = 0; + } + + if (ssdb.lanes > CIO2_MAX_LANES) { + dev_err(&adev->dev, "Number of lanes in SSDB is invalid\n"); + return -EINVAL; + } + + sensor->link = ssdb.link; + sensor->lanes = ssdb.lanes; + sensor->mclkspeed = ssdb.mclkspeed; + sensor->rotation = cio2_bridge_parse_rotation(adev, &ssdb); + sensor->orientation = cio2_bridge_get_orientation(adev); + + if (ssdb.vcmtype) + sensor->vcm_type = cio2_vcm_types[ssdb.vcmtype - 1]; + + return 0; +} + static void cio2_bridge_create_fwnode_properties( struct cio2_sensor *sensor, struct cio2_bridge *bridge, const struct cio2_sensor_config *cfg) { - u32 rotation; - - rotation = cio2_bridge_parse_rotation(sensor); - sensor->prop_names = prop_names; sensor->local_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_CIO2_ENDPOINT]); @@ -164,14 +193,14 @@ static void cio2_bridge_create_fwnode_properties( sensor->dev_properties[0] = PROPERTY_ENTRY_U32( sensor->prop_names.clock_frequency, - sensor->ssdb.mclkspeed); + sensor->mclkspeed); sensor->dev_properties[1] = PROPERTY_ENTRY_U32( sensor->prop_names.rotation, - rotation); + sensor->rotation); sensor->dev_properties[2] = PROPERTY_ENTRY_U32( sensor->prop_names.orientation, sensor->orientation); - if (sensor->ssdb.vcmtype) { + if (sensor->vcm_type) { sensor->vcm_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_VCM]); sensor->dev_properties[3] = @@ -183,8 +212,7 @@ static void cio2_bridge_create_fwnode_properties( V4L2_FWNODE_BUS_TYPE_CSI2_DPHY); sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN( sensor->prop_names.data_lanes, - bridge->data_lanes, - sensor->ssdb.lanes); + bridge->data_lanes, sensor->lanes); sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY( sensor->prop_names.remote_endpoint, sensor->local_ref); @@ -197,8 +225,7 @@ static void cio2_bridge_create_fwnode_properties( sensor->cio2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN( sensor->prop_names.data_lanes, - bridge->data_lanes, - sensor->ssdb.lanes); + bridge->data_lanes, sensor->lanes); sensor->cio2_properties[1] = PROPERTY_ENTRY_REF_ARRAY( sensor->prop_names.remote_endpoint, sensor->remote_ref); @@ -208,18 +235,17 @@ static void cio2_bridge_init_swnode_names(struct cio2_sensor *sensor) { snprintf(sensor->node_names.remote_port, sizeof(sensor->node_names.remote_port), - SWNODE_GRAPH_PORT_NAME_FMT, sensor->ssdb.link); + SWNODE_GRAPH_PORT_NAME_FMT, sensor->link); snprintf(sensor->node_names.port, sizeof(sensor->node_names.port), SWNODE_GRAPH_PORT_NAME_FMT, 0); /* Always port 0 */ snprintf(sensor->node_names.endpoint, sizeof(sensor->node_names.endpoint), SWNODE_GRAPH_ENDPOINT_NAME_FMT, 0); /* And endpoint 0 */ - if (sensor->ssdb.vcmtype) { - /* append ssdb.link to distinguish nodes with same model VCM */ + if (sensor->vcm_type) { + /* append link to distinguish nodes with same model VCM */ snprintf(sensor->node_names.vcm, sizeof(sensor->node_names.vcm), - "%s-%u", cio2_vcm_types[sensor->ssdb.vcmtype - 1], - sensor->ssdb.link); + "%s-%u", sensor->vcm_type, sensor->link); } } @@ -232,7 +258,7 @@ static void cio2_bridge_init_swnode_group(struct cio2_sensor *sensor) sensor->group[SWNODE_SENSOR_ENDPOINT] = &nodes[SWNODE_SENSOR_ENDPOINT]; sensor->group[SWNODE_CIO2_PORT] = &nodes[SWNODE_CIO2_PORT]; sensor->group[SWNODE_CIO2_ENDPOINT] = &nodes[SWNODE_CIO2_ENDPOINT]; - if (sensor->ssdb.vcmtype) + if (sensor->vcm_type) sensor->group[SWNODE_VCM] = &nodes[SWNODE_VCM]; } @@ -267,13 +293,12 @@ static void cio2_bridge_instantiate_vcm_i2c_client(struct cio2_sensor *sensor) struct i2c_board_info board_info = { }; char name[16]; - if (!sensor->ssdb.vcmtype) + if (!sensor->vcm_type) return; snprintf(name, sizeof(name), "%s-VCM", acpi_dev_name(sensor->adev)); board_info.dev_name = name; - strscpy(board_info.type, cio2_vcm_types[sensor->ssdb.vcmtype - 1], - ARRAY_SIZE(board_info.type)); + strscpy(board_info.type, sensor->vcm_type, ARRAY_SIZE(board_info.type)); board_info.swnode = &sensor->swnodes[SWNODE_VCM]; sensor->vcm_i2c_client = @@ -319,29 +344,12 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, sensor = &bridge->sensors[bridge->n_sensors]; - ret = cio2_bridge_read_acpi_buffer(adev, "SSDB", - &sensor->ssdb, - sizeof(sensor->ssdb)); + ret = cio2_bridge_parse_sensor_fwnode(adev, sensor); if (ret) goto err_put_adev; snprintf(sensor->name, sizeof(sensor->name), "%s-%u", - cfg->hid, sensor->ssdb.link); - - if (sensor->ssdb.vcmtype > ARRAY_SIZE(cio2_vcm_types)) { - dev_warn(&adev->dev, "Unknown VCM type %d\n", - sensor->ssdb.vcmtype); - sensor->ssdb.vcmtype = 0; - } - - sensor->orientation = cio2_bridge_get_orientation(adev); - - if (sensor->ssdb.lanes > CIO2_MAX_LANES) { - dev_err(&adev->dev, - "Number of lanes in SSDB is invalid\n"); - ret = -EINVAL; - goto err_put_adev; - } + cfg->hid, sensor->link); cio2_bridge_create_fwnode_properties(sensor, bridge, cfg); cio2_bridge_create_connection_swnodes(bridge, sensor); diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h index e42c5c3cf856..d53ce0c78e83 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.h +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h @@ -124,8 +124,12 @@ struct cio2_sensor { struct software_node swnodes[SWNODE_COUNT]; struct cio2_node_names node_names; - struct cio2_sensor_ssdb ssdb; + u8 link; + u8 lanes; + u32 mclkspeed; + u32 rotation; enum v4l2_fwnode_orientation orientation; + const char *vcm_type; struct cio2_property_names prop_names; struct property_entry ep_properties[5]; From patchwork Tue Jun 27 17:56:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 13294875 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 99E2CEB64DC for ; Tue, 27 Jun 2023 17:58:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229568AbjF0R6D (ORCPT ); Tue, 27 Jun 2023 13:58:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37716 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231143AbjF0R6A (ORCPT ); Tue, 27 Jun 2023 13:58:00 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 18FC12D4A for ; Tue, 27 Jun 2023 10:57:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1687888620; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lPHYAhnwx0D/YUkDucAHX508Omza4wkqVCLr7LtRCYk=; b=aXNFl6VIlBfVADyPxfQiOtfWm8bvDJkTIanhfP7rystMeyTl6rD6NvhU5CNxbIOqD1iQtM LivJ0t9bZ4bQAfhWJ4gyD4QMRe7l0IP3SRlPkVUE/dJFY64ob8SCJkjl9FFY9OsT8oKR6N accgxsy/QmC7XJdYK54picFSULz5sCc= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-540-R5A84L-6MFu_rTzSSOKuvA-1; Tue, 27 Jun 2023 13:56:56 -0400 X-MC-Unique: R5A84L-6MFu_rTzSSOKuvA-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 075A03C0FC9B; Tue, 27 Jun 2023 17:56:56 +0000 (UTC) Received: from shalem.redhat.com (unknown [10.39.194.24]) by smtp.corp.redhat.com (Postfix) with ESMTP id AC9D0200A3AD; Tue, 27 Jun 2023 17:56:54 +0000 (UTC) From: Hans de Goede To: Sakari Ailus , Laurent Pinchart , Daniel Scally Cc: Hans de Goede , Mauro Carvalho Chehab , Andy Shevchenko , Kate Hsuan , Hao Yao , Bingbu Cao , linux-media@vger.kernel.org Subject: [PATCH 07/12] media: ipu3-cio2: Add a parse_sensor_fwnode callback to cio2_bridge_init() Date: Tue, 27 Jun 2023 19:56:37 +0200 Message-ID: <20230627175643.114778-8-hdegoede@redhat.com> In-Reply-To: <20230627175643.114778-1-hdegoede@redhat.com> References: <20230627175643.114778-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add a parse_sensor_fwnode callback to cio2_bridge_init(), so that cio2_bridge_init() can be used with other sensor fwnode parse functions then just cio2_bridge_parse_sensor_fwnode. This is a preparation patch for making the cio2-bridge code more generic so that it can be shared with the atomisp driver. Signed-off-by: Hans de Goede --- Note to reviewers the wrapped __cio2_bridge_init() function goes away (becomes a generic shared helper) later in this series --- drivers/media/pci/intel/ipu3/cio2-bridge.c | 17 ++++++++++++++--- drivers/media/pci/intel/ipu3/cio2-bridge.h | 3 +++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index b189c2adf858..b799053f4934 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -150,7 +150,8 @@ cio2_bridge_get_orientation(struct acpi_device *adev) } static int cio2_bridge_parse_sensor_fwnode(struct acpi_device *adev, - struct cio2_sensor *sensor) + struct cio2_sensor *sensor, + const struct cio2_sensor_config *cfg) { struct cio2_sensor_ssdb ssdb = {}; int ret; @@ -344,7 +345,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, sensor = &bridge->sensors[bridge->n_sensors]; - ret = cio2_bridge_parse_sensor_fwnode(adev, sensor); + ret = bridge->parse_sensor_fwnode(adev, sensor, cfg); if (ret) goto err_put_adev; @@ -442,7 +443,11 @@ static int cio2_bridge_sensors_are_ready(void) return ready; } -int cio2_bridge_init(struct device *dev) +static int __cio2_bridge_init( + struct device *dev, + int (*parse_sensor_fwnode)(struct acpi_device *adev, + struct cio2_sensor *sensor, + const struct cio2_sensor_config *cfg)) { struct fwnode_handle *fwnode; struct cio2_bridge *bridge; @@ -460,6 +465,7 @@ int cio2_bridge_init(struct device *dev) sizeof(bridge->cio2_node_name)); bridge->cio2_hid_node.name = bridge->cio2_node_name; bridge->dev = dev; + bridge->parse_sensor_fwnode = parse_sensor_fwnode; ret = software_node_register(&bridge->cio2_hid_node); if (ret < 0) { @@ -503,3 +509,8 @@ int cio2_bridge_init(struct device *dev) return ret; } + +int cio2_bridge_init(struct device *dev) +{ + return __cio2_bridge_init(dev, cio2_bridge_parse_sensor_fwnode); +} diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h index d53ce0c78e83..b596fae2dc1b 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.h +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h @@ -142,6 +142,9 @@ struct cio2_sensor { struct cio2_bridge { struct device *dev; + int (*parse_sensor_fwnode)(struct acpi_device *adev, + struct cio2_sensor *sensor, + const struct cio2_sensor_config *cfg); char cio2_node_name[ACPI_ID_LEN]; struct software_node cio2_hid_node; u32 data_lanes[4]; From patchwork Tue Jun 27 17:56:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 13294877 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4ED89C0015E for ; Tue, 27 Jun 2023 17:58:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231852AbjF0R6J (ORCPT ); Tue, 27 Jun 2023 13:58:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37770 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231837AbjF0R6I (ORCPT ); Tue, 27 Jun 2023 13:58:08 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F113C30F3 for ; Tue, 27 Jun 2023 10:57:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1687888621; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=LogEO9LYFMKdnZ8UkMzJ4vpiEVgHI5Xo9kkfiIz+BK0=; b=JvvOK1tpN9MpFK7Z563bJpcTFfd6FQNkOXNPD/DIL4jcYfEc7yoUQuqkixnvk/9rPTWMac /bn1oEHSxvrJ0D7SYKg5cbMrGdhPOhvjy7QWlfryfOu7GbUdxu58O9UGNO355Y8ohx9IDg 0pGPcO1ku5rG7wl1znYZrv2OSW/ti+U= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-608-60DT8kMJOQiDydkLF1zl0A-1; Tue, 27 Jun 2023 13:56:58 -0400 X-MC-Unique: 60DT8kMJOQiDydkLF1zl0A-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 88AE8800159; Tue, 27 Jun 2023 17:56:57 +0000 (UTC) Received: from shalem.redhat.com (unknown [10.39.194.24]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3A8BD200A3AD; Tue, 27 Jun 2023 17:56:56 +0000 (UTC) From: Hans de Goede To: Sakari Ailus , Laurent Pinchart , Daniel Scally Cc: Hans de Goede , Mauro Carvalho Chehab , Andy Shevchenko , Kate Hsuan , Hao Yao , Bingbu Cao , linux-media@vger.kernel.org Subject: [PATCH 08/12] media: ipu3-cio2: Add supported_sensors parameter to cio2_bridge_init() Date: Tue, 27 Jun 2023 19:56:38 +0200 Message-ID: <20230627175643.114778-9-hdegoede@redhat.com> In-Reply-To: <20230627175643.114778-1-hdegoede@redhat.com> References: <20230627175643.114778-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Add a supported_sensors parameter to cio2_bridge_init(), so that cio2_bridge_init() can be used with other bridges which have been tested with / support a different set of sensors. This is a preparation patch for making the cio2-bridge code more generic so that it can be shared with the atomisp driver. Signed-off-by: Hans de Goede --- drivers/media/pci/intel/ipu3/cio2-bridge.c | 22 +++++++++++++--------- drivers/media/pci/intel/ipu3/cio2-bridge.h | 1 + 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index b799053f4934..9da0f003af7b 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -36,6 +36,7 @@ static const struct cio2_sensor_config cio2_supported_sensors[] = { CIO2_SENSOR_CONFIG("INT3537", 1, 437000000), /* Omnivision ov13b10 */ CIO2_SENSOR_CONFIG("OVTIDB10", 1, 560000000), + {} }; static const struct cio2_property_names prop_names = { @@ -393,9 +394,9 @@ static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge) unsigned int i; int ret; - for (i = 0; i < ARRAY_SIZE(cio2_supported_sensors); i++) { + for (i = 0; bridge->supported_sensors[i].hid; i++) { const struct cio2_sensor_config *cfg = - &cio2_supported_sensors[i]; + &bridge->supported_sensors[i]; ret = cio2_bridge_connect_sensor(cfg, bridge); if (ret) @@ -421,15 +422,15 @@ static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge) * acpi_dev_ready_for_enumeration() helper, like the i2c-core-acpi code does * for the sensors. */ -static int cio2_bridge_sensors_are_ready(void) +static int cio2_bridge_sensors_are_ready( + const struct cio2_sensor_config *supported_sensors) { struct acpi_device *adev; bool ready = true; unsigned int i; - for (i = 0; i < ARRAY_SIZE(cio2_supported_sensors); i++) { - const struct cio2_sensor_config *cfg = - &cio2_supported_sensors[i]; + for (i = 0; supported_sensors[i].hid; i++) { + const struct cio2_sensor_config *cfg = &supported_sensors[i]; for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { if (!adev->status.enabled) @@ -447,14 +448,15 @@ static int __cio2_bridge_init( struct device *dev, int (*parse_sensor_fwnode)(struct acpi_device *adev, struct cio2_sensor *sensor, - const struct cio2_sensor_config *cfg)) + const struct cio2_sensor_config *cfg), + const struct cio2_sensor_config *supported_sensors) { struct fwnode_handle *fwnode; struct cio2_bridge *bridge; unsigned int i; int ret; - if (!cio2_bridge_sensors_are_ready()) + if (!cio2_bridge_sensors_are_ready(supported_sensors)) return -EPROBE_DEFER; bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); @@ -466,6 +468,7 @@ static int __cio2_bridge_init( bridge->cio2_hid_node.name = bridge->cio2_node_name; bridge->dev = dev; bridge->parse_sensor_fwnode = parse_sensor_fwnode; + bridge->supported_sensors = supported_sensors; ret = software_node_register(&bridge->cio2_hid_node); if (ret < 0) { @@ -512,5 +515,6 @@ static int __cio2_bridge_init( int cio2_bridge_init(struct device *dev) { - return __cio2_bridge_init(dev, cio2_bridge_parse_sensor_fwnode); + return __cio2_bridge_init(dev, cio2_bridge_parse_sensor_fwnode, + cio2_supported_sensors); } diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h index b596fae2dc1b..e646cb17ab20 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.h +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h @@ -145,6 +145,7 @@ struct cio2_bridge { int (*parse_sensor_fwnode)(struct acpi_device *adev, struct cio2_sensor *sensor, const struct cio2_sensor_config *cfg); + const struct cio2_sensor_config *supported_sensors; char cio2_node_name[ACPI_ID_LEN]; struct software_node cio2_hid_node; u32 data_lanes[4]; From patchwork Tue Jun 27 17:56:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 13294876 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 730F1EB64D9 for ; Tue, 27 Jun 2023 17:58:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231861AbjF0R6H (ORCPT ); Tue, 27 Jun 2023 13:58:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37830 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231837AbjF0R6G (ORCPT ); Tue, 27 Jun 2023 13:58:06 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 06EB530F4 for ; Tue, 27 Jun 2023 10:57:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1687888621; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PPfWMXD4ulM8eQHrpWdbTifaZqC0EFJ7fnAx5EfEhGc=; b=hzFRk7Oiv15QK9nsKLrbGhOF44QMsvGpqijFODek7xvQ9QnH7Hg6IM378F1AiBfSquB0rn FuELrxdjx1vFQ79JWxQ3MlblQ0DZ3flPlgKKZE3a/0hrVGh+mQgeI7yUfrrXrIznFrDyDK T+P4v8ZNGj03aKwKOsPXFeVRneHq3gc= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-610-xzGVDypdMlSv07AHSi3MIA-1; Tue, 27 Jun 2023 13:56:59 -0400 X-MC-Unique: xzGVDypdMlSv07AHSi3MIA-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 30816185A793; Tue, 27 Jun 2023 17:56:59 +0000 (UTC) Received: from shalem.redhat.com (unknown [10.39.194.24]) by smtp.corp.redhat.com (Postfix) with ESMTP id BC2D62014E17; Tue, 27 Jun 2023 17:56:57 +0000 (UTC) From: Hans de Goede To: Sakari Ailus , Laurent Pinchart , Daniel Scally Cc: Hans de Goede , Mauro Carvalho Chehab , Andy Shevchenko , Kate Hsuan , Hao Yao , Bingbu Cao , linux-media@vger.kernel.org Subject: [PATCH 09/12] media: ipu3-cio2: Move cio2_bridge_init() code into a new shared intel-cio2-bridge.ko Date: Tue, 27 Jun 2023 19:56:39 +0200 Message-ID: <20230627175643.114778-10-hdegoede@redhat.com> In-Reply-To: <20230627175643.114778-1-hdegoede@redhat.com> References: <20230627175643.114778-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Move all the code implementing cio2_bridge_init() into a new shared intel-cio2-bridge.ko, so that it can be reused by the atomisp driver (and maybe also by the future IPU6 CSI2 driver). Note this just moves a bunch of stuff around prefixes some symbols / defines with intel_ / INTEL_ no functional changes. Signed-off-by: Hans de Goede --- MAINTAINERS | 9 + drivers/media/common/Kconfig | 4 + drivers/media/common/Makefile | 1 + .../intel-cio2-bridge.c} | 228 +++------ drivers/media/pci/intel/ipu3/Kconfig | 1 + drivers/media/pci/intel/ipu3/cio2-bridge.c | 438 +++--------------- drivers/media/pci/intel/ipu3/cio2-bridge.h | 156 ------- include/media/intel-cio2-bridge.h | 104 +++++ 8 files changed, 237 insertions(+), 704 deletions(-) copy drivers/media/{pci/intel/ipu3/cio2-bridge.c => common/intel-cio2-bridge.c} (66%) delete mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h create mode 100644 include/media/intel-cio2-bridge.h diff --git a/MAINTAINERS b/MAINTAINERS index 2ec35c3569dd..89ea1266ef4b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10325,6 +10325,15 @@ S: Supported T: git git://git.code.sf.net/p/intel-sas/isci F: drivers/scsi/isci/ +INTEL CIO2 ACPI SENSOR BRIDGE +M: Dan Scally +M: Hans de Goede +L: linux-media@vger.kernel.org +S: Maintained +T: git git://linuxtv.org/media_tree.git +F: drivers/media/common/intel-cio2-bridge.c +F: include/media/intel-cio2-bridge.h + INTEL CPU family model numbers M: Tony Luck M: x86@kernel.org diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig index adcb6655385a..e7a9d1b1630c 100644 --- a/drivers/media/common/Kconfig +++ b/drivers/media/common/Kconfig @@ -10,6 +10,10 @@ config CYPRESS_FIRMWARE tristate depends on USB +config INTEL_CIO2_BRIDGE + tristate + depends on ACPI && I2C + config TTPCI_EEPROM tristate depends on I2C diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile index c5ab905e7c20..728aaf90b6ec 100644 --- a/drivers/media/common/Makefile +++ b/drivers/media/common/Makefile @@ -4,6 +4,7 @@ obj-y += b2c2/ saa7146/ siano/ v4l2-tpg/ videobuf2/ # Please keep it alphabetically sorted by Kconfig name # (e. g. LC_ALL=C sort Makefile) obj-$(CONFIG_CYPRESS_FIRMWARE) += cypress_firmware.o +obj-$(CONFIG_INTEL_CIO2_BRIDGE) += intel-cio2-bridge.o obj-$(CONFIG_TTPCI_EEPROM) += ttpci-eeprom.o obj-$(CONFIG_UVC_COMMON) += uvc.o obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/common/intel-cio2-bridge.c similarity index 66% copy from drivers/media/pci/intel/ipu3/cio2-bridge.c copy to drivers/media/common/intel-cio2-bridge.c index 9da0f003af7b..2f4256f9152c 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/common/intel-cio2-bridge.c @@ -1,45 +1,40 @@ // SPDX-License-Identifier: GPL-2.0 /* Author: Dan Scally */ +/* Author: Hans de Goede */ #include #include #include #include + +#include #include -#include "cio2-bridge.h" +#define NODE_SENSOR(_HID, _PROPS) \ + (const struct software_node) { \ + .name = _HID, \ + .properties = _PROPS, \ + } -/* - * Extend this array with ACPI Hardware IDs of devices known to be working - * plus the number of link-frequencies expected by their drivers, along with - * the frequency values in hertz. This is somewhat opportunistic way of adding - * support for this for now in the hopes of a better source for the information - * (possibly some encoded value in the SSDB buffer that we're unaware of) - * becoming apparent in the future. - * - * Do not add an entry for a sensor that is not actually supported. - */ -static const struct cio2_sensor_config cio2_supported_sensors[] = { - /* Omnivision OV5693 */ - CIO2_SENSOR_CONFIG("INT33BE", 1, 419200000), - /* Omnivision OV8865 */ - CIO2_SENSOR_CONFIG("INT347A", 1, 360000000), - /* Omnivision OV7251 */ - CIO2_SENSOR_CONFIG("INT347E", 1, 319200000), - /* Omnivision OV2680 */ - CIO2_SENSOR_CONFIG("OVTI2680", 0), - /* Omnivision ov8856 */ - CIO2_SENSOR_CONFIG("OVTI8856", 3, 180000000, 360000000, 720000000), - /* Omnivision ov2740 */ - CIO2_SENSOR_CONFIG("INT3474", 1, 360000000), - /* Hynix hi556 */ - CIO2_SENSOR_CONFIG("INT3537", 1, 437000000), - /* Omnivision ov13b10 */ - CIO2_SENSOR_CONFIG("OVTIDB10", 1, 560000000), - {} -}; +#define NODE_PORT(_PORT, _SENSOR_NODE) \ + (const struct software_node) { \ + .name = _PORT, \ + .parent = _SENSOR_NODE, \ + } -static const struct cio2_property_names prop_names = { +#define NODE_ENDPOINT(_EP, _PORT, _PROPS) \ + (const struct software_node) { \ + .name = _EP, \ + .parent = _PORT, \ + .properties = _PROPS, \ + } + +#define NODE_VCM(_TYPE) \ + (const struct software_node) { \ + .name = _TYPE, \ + } + +static const struct intel_cio2_property_names prop_names = { .clock_frequency = "clock-frequency", .rotation = "rotation", .orientation = "orientation", @@ -49,73 +44,8 @@ static const struct cio2_property_names prop_names = { .link_frequencies = "link-frequencies", }; -static const char * const cio2_vcm_types[] = { - "ad5823", - "dw9714", - "ad5816", - "dw9719", - "dw9718", - "dw9806b", - "wv517s", - "lc898122xa", - "lc898212axb", -}; - -static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id, - void *data, u32 size) -{ - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - acpi_status status; - int ret = 0; - - status = acpi_evaluate_object(adev->handle, id, NULL, &buffer); - if (ACPI_FAILURE(status)) - return -ENODEV; - - obj = buffer.pointer; - if (!obj) { - dev_err(&adev->dev, "Couldn't locate ACPI buffer\n"); - return -ENODEV; - } - - if (obj->type != ACPI_TYPE_BUFFER) { - dev_err(&adev->dev, "Not an ACPI buffer\n"); - ret = -ENODEV; - goto out_free_buff; - } - - if (obj->buffer.length > size) { - dev_err(&adev->dev, "Given buffer is too small\n"); - ret = -EINVAL; - goto out_free_buff; - } - - memcpy(data, obj->buffer.pointer, obj->buffer.length); - -out_free_buff: - kfree(buffer.pointer); - return ret; -} - -static u32 cio2_bridge_parse_rotation(struct acpi_device *adev, - struct cio2_sensor_ssdb *ssdb) -{ - switch (ssdb->degree) { - case CIO2_SENSOR_ROTATION_NORMAL: - return 0; - case CIO2_SENSOR_ROTATION_INVERTED: - return 180; - default: - dev_warn(&adev->dev, - "Unknown rotation %d. Assume 0 degree rotation\n", - ssdb->degree); - return 0; - } -} - -static enum v4l2_fwnode_orientation -cio2_bridge_get_orientation(struct acpi_device *adev) +enum v4l2_fwnode_orientation +intel_cio2_bridge_get_orientation(struct acpi_device *adev) { enum v4l2_fwnode_orientation orientation; struct acpi_pld_info *pld; @@ -149,44 +79,12 @@ cio2_bridge_get_orientation(struct acpi_device *adev) ACPI_FREE(pld); return orientation; } - -static int cio2_bridge_parse_sensor_fwnode(struct acpi_device *adev, - struct cio2_sensor *sensor, - const struct cio2_sensor_config *cfg) -{ - struct cio2_sensor_ssdb ssdb = {}; - int ret; - - ret = cio2_bridge_read_acpi_buffer(adev, "SSDB", &ssdb, sizeof(ssdb)); - if (ret) - return ret; - - if (ssdb.vcmtype > ARRAY_SIZE(cio2_vcm_types)) { - dev_warn(&adev->dev, "Unknown VCM type %d\n", ssdb.vcmtype); - ssdb.vcmtype = 0; - } - - if (ssdb.lanes > CIO2_MAX_LANES) { - dev_err(&adev->dev, "Number of lanes in SSDB is invalid\n"); - return -EINVAL; - } - - sensor->link = ssdb.link; - sensor->lanes = ssdb.lanes; - sensor->mclkspeed = ssdb.mclkspeed; - sensor->rotation = cio2_bridge_parse_rotation(adev, &ssdb); - sensor->orientation = cio2_bridge_get_orientation(adev); - - if (ssdb.vcmtype) - sensor->vcm_type = cio2_vcm_types[ssdb.vcmtype - 1]; - - return 0; -} +EXPORT_SYMBOL(intel_cio2_bridge_get_orientation); static void cio2_bridge_create_fwnode_properties( - struct cio2_sensor *sensor, - struct cio2_bridge *bridge, - const struct cio2_sensor_config *cfg) + struct intel_cio2_sensor *sensor, + struct intel_cio2_bridge *bridge, + const struct intel_cio2_sensor_config *cfg) { sensor->prop_names = prop_names; @@ -233,7 +131,7 @@ static void cio2_bridge_create_fwnode_properties( sensor->remote_ref); } -static void cio2_bridge_init_swnode_names(struct cio2_sensor *sensor) +static void cio2_bridge_init_swnode_names(struct intel_cio2_sensor *sensor) { snprintf(sensor->node_names.remote_port, sizeof(sensor->node_names.remote_port), @@ -251,7 +149,7 @@ static void cio2_bridge_init_swnode_names(struct cio2_sensor *sensor) } } -static void cio2_bridge_init_swnode_group(struct cio2_sensor *sensor) +static void cio2_bridge_init_swnode_group(struct intel_cio2_sensor *sensor) { struct software_node *nodes = sensor->swnodes; @@ -264,8 +162,9 @@ static void cio2_bridge_init_swnode_group(struct cio2_sensor *sensor) sensor->group[SWNODE_VCM] = &nodes[SWNODE_VCM]; } -static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge, - struct cio2_sensor *sensor) +static void cio2_bridge_create_connection_swnodes( + struct intel_cio2_bridge *bridge, + struct intel_cio2_sensor *sensor) { struct software_node *nodes = sensor->swnodes; @@ -290,7 +189,8 @@ static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge, cio2_bridge_init_swnode_group(sensor); } -static void cio2_bridge_instantiate_vcm_i2c_client(struct cio2_sensor *sensor) +static void cio2_bridge_instantiate_vcm_i2c_client( + struct intel_cio2_sensor *sensor) { struct i2c_board_info board_info = { }; char name[16]; @@ -313,9 +213,9 @@ static void cio2_bridge_instantiate_vcm_i2c_client(struct cio2_sensor *sensor) } } -static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge) +static void cio2_bridge_unregister_sensors(struct intel_cio2_bridge *bridge) { - struct cio2_sensor *sensor; + struct intel_cio2_sensor *sensor; unsigned int i; for (i = 0; i < bridge->n_sensors; i++) { @@ -326,11 +226,12 @@ static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge) } } -static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, - struct cio2_bridge *bridge) +static int cio2_bridge_connect_sensor( + const struct intel_cio2_sensor_config *cfg, + struct intel_cio2_bridge *bridge) { struct fwnode_handle *fwnode, *primary; - struct cio2_sensor *sensor; + struct intel_cio2_sensor *sensor; struct acpi_device *adev; int ret; @@ -338,7 +239,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, if (!adev->status.enabled) continue; - if (bridge->n_sensors >= CIO2_NUM_PORTS) { + if (bridge->n_sensors >= INTEL_CIO2_NUM_PORTS) { acpi_dev_put(adev); dev_err(bridge->dev, "Exceeded available CIO2 ports\n"); return -EINVAL; @@ -389,13 +290,13 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, return ret; } -static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge) +static int cio2_bridge_connect_sensors(struct intel_cio2_bridge *bridge) { unsigned int i; int ret; for (i = 0; bridge->supported_sensors[i].hid; i++) { - const struct cio2_sensor_config *cfg = + const struct intel_cio2_sensor_config *cfg = &bridge->supported_sensors[i]; ret = cio2_bridge_connect_sensor(cfg, bridge); @@ -423,14 +324,15 @@ static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge) * for the sensors. */ static int cio2_bridge_sensors_are_ready( - const struct cio2_sensor_config *supported_sensors) + const struct intel_cio2_sensor_config *supported_sensors) { struct acpi_device *adev; bool ready = true; unsigned int i; for (i = 0; supported_sensors[i].hid; i++) { - const struct cio2_sensor_config *cfg = &supported_sensors[i]; + const struct intel_cio2_sensor_config *cfg = + &supported_sensors[i]; for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { if (!adev->status.enabled) @@ -444,15 +346,15 @@ static int cio2_bridge_sensors_are_ready( return ready; } -static int __cio2_bridge_init( +int intel_cio2_bridge_init( struct device *dev, int (*parse_sensor_fwnode)(struct acpi_device *adev, - struct cio2_sensor *sensor, - const struct cio2_sensor_config *cfg), - const struct cio2_sensor_config *supported_sensors) + struct intel_cio2_sensor *sensor, + const struct intel_cio2_sensor_config *cfg), + const struct intel_cio2_sensor_config *supported_sensors) { struct fwnode_handle *fwnode; - struct cio2_bridge *bridge; + struct intel_cio2_bridge *bridge; unsigned int i; int ret; @@ -463,7 +365,7 @@ static int __cio2_bridge_init( if (!bridge) return -ENOMEM; - strscpy(bridge->cio2_node_name, CIO2_HID, + strscpy(bridge->cio2_node_name, INTEL_CIO2_HID, sizeof(bridge->cio2_node_name)); bridge->cio2_hid_node.name = bridge->cio2_node_name; bridge->dev = dev; @@ -478,12 +380,12 @@ static int __cio2_bridge_init( /* * Map the lane arrangement, which is fixed for the IPU3 (meaning we - * only need one, rather than one per sensor). We include it as a - * member of the struct cio2_bridge rather than a global variable so + * only need one, rather than one per sensor). We include it as a member + * of the struct intel_cio2_bridge rather than a global variable so * that it survives if the module is unloaded along with the rest of * the struct. */ - for (i = 0; i < CIO2_MAX_LANES; i++) + for (i = 0; i < INTEL_CIO2_MAX_LANES; i++) bridge->data_lanes[i] = i + 1; ret = cio2_bridge_connect_sensors(bridge); @@ -512,9 +414,9 @@ static int __cio2_bridge_init( return ret; } +EXPORT_SYMBOL(intel_cio2_bridge_init); -int cio2_bridge_init(struct device *dev) -{ - return __cio2_bridge_init(dev, cio2_bridge_parse_sensor_fwnode, - cio2_supported_sensors); -} +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Dan Scally "); +MODULE_AUTHOR("Hans de Goede "); +MODULE_DESCRIPTION("Intel CIO2 ACPI Sensors Bridge"); diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig index 65b0c1598fbf..3c32e4d536ad 100644 --- a/drivers/media/pci/intel/ipu3/Kconfig +++ b/drivers/media/pci/intel/ipu3/Kconfig @@ -8,6 +8,7 @@ config VIDEO_IPU3_CIO2 select VIDEO_V4L2_SUBDEV_API select V4L2_FWNODE select VIDEOBUF2_DMA_SG + select INTEL_CIO2_BRIDGE if CIO2_BRIDGE help This is the Intel IPU3 CIO2 CSI-2 receiver unit, found in Intel diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index 9da0f003af7b..f833637fe938 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -5,9 +5,52 @@ #include #include #include + +#include #include -#include "cio2-bridge.h" +#include "ipu3-cio2.h" + +/* Data representation as it is in ACPI SSDB buffer */ +struct cio2_sensor_ssdb { + u8 version; + u8 sku; + u8 guid_csi2[16]; + u8 devfunction; + u8 bus; + u32 dphylinkenfuses; + u32 clockdiv; + u8 link; + u8 lanes; + u32 csiparams[10]; + u32 maxlanespeed; + u8 sensorcalibfileidx; + u8 sensorcalibfileidxInMBZ[3]; + u8 romtype; + u8 vcmtype; + u8 platforminfo; + u8 platformsubinfo; + u8 flash; + u8 privacyled; + u8 degree; + u8 mipilinkdefined; + u32 mclkspeed; + u8 controllogicid; + u8 reserved1[3]; + u8 mclkport; + u8 reserved2[13]; +} __packed; + +/* Values are educated guesses as we don't have a spec */ +#define CIO2_SENSOR_ROTATION_NORMAL 0 +#define CIO2_SENSOR_ROTATION_INVERTED 1 + +#define CIO2_SENSOR_CONFIG(_HID, _NR, ...) \ + (const struct intel_cio2_sensor_config) { \ + .hid = _HID, \ + .nr_link_freqs = _NR, \ + .link_freqs = { __VA_ARGS__ } \ + } /* * Extend this array with ACPI Hardware IDs of devices known to be working @@ -19,7 +62,7 @@ * * Do not add an entry for a sensor that is not actually supported. */ -static const struct cio2_sensor_config cio2_supported_sensors[] = { +static const struct intel_cio2_sensor_config cio2_supported_sensors[] = { /* Omnivision OV5693 */ CIO2_SENSOR_CONFIG("INT33BE", 1, 419200000), /* Omnivision OV8865 */ @@ -39,16 +82,6 @@ static const struct cio2_sensor_config cio2_supported_sensors[] = { {} }; -static const struct cio2_property_names prop_names = { - .clock_frequency = "clock-frequency", - .rotation = "rotation", - .orientation = "orientation", - .bus_type = "bus-type", - .data_lanes = "data-lanes", - .remote_endpoint = "remote-endpoint", - .link_frequencies = "link-frequencies", -}; - static const char * const cio2_vcm_types[] = { "ad5823", "dw9714", @@ -114,45 +147,10 @@ static u32 cio2_bridge_parse_rotation(struct acpi_device *adev, } } -static enum v4l2_fwnode_orientation -cio2_bridge_get_orientation(struct acpi_device *adev) -{ - enum v4l2_fwnode_orientation orientation; - struct acpi_pld_info *pld; - acpi_status status; - - status = acpi_get_physical_device_location(adev->handle, &pld); - if (ACPI_FAILURE(status)) { - dev_warn(&adev->dev, "_PLD call failed using unknown orientation\n"); - return V4L2_FWNODE_ORIENTATION_EXTERNAL; - } - - switch (pld->panel) { - case ACPI_PLD_PANEL_FRONT: - orientation = V4L2_FWNODE_ORIENTATION_FRONT; - break; - case ACPI_PLD_PANEL_BACK: - orientation = V4L2_FWNODE_ORIENTATION_BACK; - break; - case ACPI_PLD_PANEL_TOP: - case ACPI_PLD_PANEL_LEFT: - case ACPI_PLD_PANEL_RIGHT: - case ACPI_PLD_PANEL_UNKNOWN: - orientation = V4L2_FWNODE_ORIENTATION_EXTERNAL; - break; - default: - dev_warn(&adev->dev, "Unknown _PLD panel val %d\n", pld->panel); - orientation = V4L2_FWNODE_ORIENTATION_EXTERNAL; - break; - } - - ACPI_FREE(pld); - return orientation; -} - -static int cio2_bridge_parse_sensor_fwnode(struct acpi_device *adev, - struct cio2_sensor *sensor, - const struct cio2_sensor_config *cfg) +static int cio2_bridge_parse_sensor_fwnode( + struct acpi_device *adev, + struct intel_cio2_sensor *sensor, + const struct intel_cio2_sensor_config *cfg) { struct cio2_sensor_ssdb ssdb = {}; int ret; @@ -166,7 +164,7 @@ static int cio2_bridge_parse_sensor_fwnode(struct acpi_device *adev, ssdb.vcmtype = 0; } - if (ssdb.lanes > CIO2_MAX_LANES) { + if (ssdb.lanes > INTEL_CIO2_MAX_LANES) { dev_err(&adev->dev, "Number of lanes in SSDB is invalid\n"); return -EINVAL; } @@ -175,7 +173,7 @@ static int cio2_bridge_parse_sensor_fwnode(struct acpi_device *adev, sensor->lanes = ssdb.lanes; sensor->mclkspeed = ssdb.mclkspeed; sensor->rotation = cio2_bridge_parse_rotation(adev, &ssdb); - sensor->orientation = cio2_bridge_get_orientation(adev); + sensor->orientation = intel_cio2_bridge_get_orientation(adev); if (ssdb.vcmtype) sensor->vcm_type = cio2_vcm_types[ssdb.vcmtype - 1]; @@ -183,338 +181,8 @@ static int cio2_bridge_parse_sensor_fwnode(struct acpi_device *adev, return 0; } -static void cio2_bridge_create_fwnode_properties( - struct cio2_sensor *sensor, - struct cio2_bridge *bridge, - const struct cio2_sensor_config *cfg) -{ - sensor->prop_names = prop_names; - - sensor->local_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_CIO2_ENDPOINT]); - sensor->remote_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_SENSOR_ENDPOINT]); - - sensor->dev_properties[0] = PROPERTY_ENTRY_U32( - sensor->prop_names.clock_frequency, - sensor->mclkspeed); - sensor->dev_properties[1] = PROPERTY_ENTRY_U32( - sensor->prop_names.rotation, - sensor->rotation); - sensor->dev_properties[2] = PROPERTY_ENTRY_U32( - sensor->prop_names.orientation, - sensor->orientation); - if (sensor->vcm_type) { - sensor->vcm_ref[0] = - SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_VCM]); - sensor->dev_properties[3] = - PROPERTY_ENTRY_REF_ARRAY("lens-focus", sensor->vcm_ref); - } - - sensor->ep_properties[0] = PROPERTY_ENTRY_U32( - sensor->prop_names.bus_type, - V4L2_FWNODE_BUS_TYPE_CSI2_DPHY); - sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN( - sensor->prop_names.data_lanes, - bridge->data_lanes, sensor->lanes); - sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY( - sensor->prop_names.remote_endpoint, - sensor->local_ref); - - if (cfg->nr_link_freqs > 0) - sensor->ep_properties[3] = PROPERTY_ENTRY_U64_ARRAY_LEN( - sensor->prop_names.link_frequencies, - cfg->link_freqs, - cfg->nr_link_freqs); - - sensor->cio2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN( - sensor->prop_names.data_lanes, - bridge->data_lanes, sensor->lanes); - sensor->cio2_properties[1] = PROPERTY_ENTRY_REF_ARRAY( - sensor->prop_names.remote_endpoint, - sensor->remote_ref); -} - -static void cio2_bridge_init_swnode_names(struct cio2_sensor *sensor) -{ - snprintf(sensor->node_names.remote_port, - sizeof(sensor->node_names.remote_port), - SWNODE_GRAPH_PORT_NAME_FMT, sensor->link); - snprintf(sensor->node_names.port, - sizeof(sensor->node_names.port), - SWNODE_GRAPH_PORT_NAME_FMT, 0); /* Always port 0 */ - snprintf(sensor->node_names.endpoint, - sizeof(sensor->node_names.endpoint), - SWNODE_GRAPH_ENDPOINT_NAME_FMT, 0); /* And endpoint 0 */ - if (sensor->vcm_type) { - /* append link to distinguish nodes with same model VCM */ - snprintf(sensor->node_names.vcm, sizeof(sensor->node_names.vcm), - "%s-%u", sensor->vcm_type, sensor->link); - } -} - -static void cio2_bridge_init_swnode_group(struct cio2_sensor *sensor) -{ - struct software_node *nodes = sensor->swnodes; - - sensor->group[SWNODE_SENSOR_HID] = &nodes[SWNODE_SENSOR_HID]; - sensor->group[SWNODE_SENSOR_PORT] = &nodes[SWNODE_SENSOR_PORT]; - sensor->group[SWNODE_SENSOR_ENDPOINT] = &nodes[SWNODE_SENSOR_ENDPOINT]; - sensor->group[SWNODE_CIO2_PORT] = &nodes[SWNODE_CIO2_PORT]; - sensor->group[SWNODE_CIO2_ENDPOINT] = &nodes[SWNODE_CIO2_ENDPOINT]; - if (sensor->vcm_type) - sensor->group[SWNODE_VCM] = &nodes[SWNODE_VCM]; -} - -static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge, - struct cio2_sensor *sensor) -{ - struct software_node *nodes = sensor->swnodes; - - cio2_bridge_init_swnode_names(sensor); - - nodes[SWNODE_SENSOR_HID] = NODE_SENSOR(sensor->name, - sensor->dev_properties); - nodes[SWNODE_SENSOR_PORT] = NODE_PORT(sensor->node_names.port, - &nodes[SWNODE_SENSOR_HID]); - nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT( - sensor->node_names.endpoint, - &nodes[SWNODE_SENSOR_PORT], - sensor->ep_properties); - nodes[SWNODE_CIO2_PORT] = NODE_PORT(sensor->node_names.remote_port, - &bridge->cio2_hid_node); - nodes[SWNODE_CIO2_ENDPOINT] = NODE_ENDPOINT( - sensor->node_names.endpoint, - &nodes[SWNODE_CIO2_PORT], - sensor->cio2_properties); - nodes[SWNODE_VCM] = NODE_VCM(sensor->node_names.vcm); - - cio2_bridge_init_swnode_group(sensor); -} - -static void cio2_bridge_instantiate_vcm_i2c_client(struct cio2_sensor *sensor) -{ - struct i2c_board_info board_info = { }; - char name[16]; - - if (!sensor->vcm_type) - return; - - snprintf(name, sizeof(name), "%s-VCM", acpi_dev_name(sensor->adev)); - board_info.dev_name = name; - strscpy(board_info.type, sensor->vcm_type, ARRAY_SIZE(board_info.type)); - board_info.swnode = &sensor->swnodes[SWNODE_VCM]; - - sensor->vcm_i2c_client = - i2c_acpi_new_device_by_fwnode(acpi_fwnode_handle(sensor->adev), - 1, &board_info); - if (IS_ERR(sensor->vcm_i2c_client)) { - dev_warn(&sensor->adev->dev, "Error instantiation VCM i2c-client: %ld\n", - PTR_ERR(sensor->vcm_i2c_client)); - sensor->vcm_i2c_client = NULL; - } -} - -static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge) -{ - struct cio2_sensor *sensor; - unsigned int i; - - for (i = 0; i < bridge->n_sensors; i++) { - sensor = &bridge->sensors[i]; - software_node_unregister_node_group(sensor->group); - acpi_dev_put(sensor->adev); - i2c_unregister_device(sensor->vcm_i2c_client); - } -} - -static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, - struct cio2_bridge *bridge) -{ - struct fwnode_handle *fwnode, *primary; - struct cio2_sensor *sensor; - struct acpi_device *adev; - int ret; - - for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { - if (!adev->status.enabled) - continue; - - if (bridge->n_sensors >= CIO2_NUM_PORTS) { - acpi_dev_put(adev); - dev_err(bridge->dev, "Exceeded available CIO2 ports\n"); - return -EINVAL; - } - - sensor = &bridge->sensors[bridge->n_sensors]; - - ret = bridge->parse_sensor_fwnode(adev, sensor, cfg); - if (ret) - goto err_put_adev; - - snprintf(sensor->name, sizeof(sensor->name), "%s-%u", - cfg->hid, sensor->link); - - cio2_bridge_create_fwnode_properties(sensor, bridge, cfg); - cio2_bridge_create_connection_swnodes(bridge, sensor); - - ret = software_node_register_node_group(sensor->group); - if (ret) - goto err_put_adev; - - fwnode = software_node_fwnode(&sensor->swnodes[ - SWNODE_SENSOR_HID]); - if (!fwnode) { - ret = -ENODEV; - goto err_free_swnodes; - } - - sensor->adev = acpi_dev_get(adev); - - primary = acpi_fwnode_handle(adev); - primary->secondary = fwnode; - - cio2_bridge_instantiate_vcm_i2c_client(sensor); - - dev_info(bridge->dev, "Found supported sensor %s\n", - acpi_dev_name(adev)); - - bridge->n_sensors++; - } - - return 0; - -err_free_swnodes: - software_node_unregister_node_group(sensor->group); -err_put_adev: - acpi_dev_put(adev); - return ret; -} - -static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge) -{ - unsigned int i; - int ret; - - for (i = 0; bridge->supported_sensors[i].hid; i++) { - const struct cio2_sensor_config *cfg = - &bridge->supported_sensors[i]; - - ret = cio2_bridge_connect_sensor(cfg, bridge); - if (ret) - goto err_unregister_sensors; - } - - return 0; - -err_unregister_sensors: - cio2_bridge_unregister_sensors(bridge); - return ret; -} - -/* - * The VCM cannot be probed until the PMIC is completely setup. We cannot rely - * on -EPROBE_DEFER for this, since the consumer<->supplier relations between - * the VCM and regulators/clks are not described in ACPI, instead they are - * passed as board-data to the PMIC drivers. Since -PROBE_DEFER does not work - * for the clks/regulators the VCM i2c-clients must not be instantiated until - * the PMIC is fully setup. - * - * The sensor/VCM ACPI device has an ACPI _DEP on the PMIC, check this using the - * acpi_dev_ready_for_enumeration() helper, like the i2c-core-acpi code does - * for the sensors. - */ -static int cio2_bridge_sensors_are_ready( - const struct cio2_sensor_config *supported_sensors) -{ - struct acpi_device *adev; - bool ready = true; - unsigned int i; - - for (i = 0; supported_sensors[i].hid; i++) { - const struct cio2_sensor_config *cfg = &supported_sensors[i]; - - for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { - if (!adev->status.enabled) - continue; - - if (!acpi_dev_ready_for_enumeration(adev)) - ready = false; - } - } - - return ready; -} - -static int __cio2_bridge_init( - struct device *dev, - int (*parse_sensor_fwnode)(struct acpi_device *adev, - struct cio2_sensor *sensor, - const struct cio2_sensor_config *cfg), - const struct cio2_sensor_config *supported_sensors) -{ - struct fwnode_handle *fwnode; - struct cio2_bridge *bridge; - unsigned int i; - int ret; - - if (!cio2_bridge_sensors_are_ready(supported_sensors)) - return -EPROBE_DEFER; - - bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); - if (!bridge) - return -ENOMEM; - - strscpy(bridge->cio2_node_name, CIO2_HID, - sizeof(bridge->cio2_node_name)); - bridge->cio2_hid_node.name = bridge->cio2_node_name; - bridge->dev = dev; - bridge->parse_sensor_fwnode = parse_sensor_fwnode; - bridge->supported_sensors = supported_sensors; - - ret = software_node_register(&bridge->cio2_hid_node); - if (ret < 0) { - dev_err(dev, "Failed to register the CIO2 HID node\n"); - goto err_free_bridge; - } - - /* - * Map the lane arrangement, which is fixed for the IPU3 (meaning we - * only need one, rather than one per sensor). We include it as a - * member of the struct cio2_bridge rather than a global variable so - * that it survives if the module is unloaded along with the rest of - * the struct. - */ - for (i = 0; i < CIO2_MAX_LANES; i++) - bridge->data_lanes[i] = i + 1; - - ret = cio2_bridge_connect_sensors(bridge); - if (ret || bridge->n_sensors == 0) - goto err_unregister_cio2; - - dev_info(dev, "Connected %d cameras\n", bridge->n_sensors); - - fwnode = software_node_fwnode(&bridge->cio2_hid_node); - if (!fwnode) { - dev_err(dev, "Error getting fwnode from cio2 software_node\n"); - ret = -ENODEV; - goto err_unregister_sensors; - } - - set_secondary_fwnode(dev, fwnode); - - return 0; - -err_unregister_sensors: - cio2_bridge_unregister_sensors(bridge); -err_unregister_cio2: - software_node_unregister(&bridge->cio2_hid_node); -err_free_bridge: - kfree(bridge); - - return ret; -} - int cio2_bridge_init(struct device *dev) { - return __cio2_bridge_init(dev, cio2_bridge_parse_sensor_fwnode, - cio2_supported_sensors); + return intel_cio2_bridge_init(dev, cio2_bridge_parse_sensor_fwnode, + cio2_supported_sensors); } diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h deleted file mode 100644 index e646cb17ab20..000000000000 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.h +++ /dev/null @@ -1,156 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Author: Dan Scally */ -#ifndef __CIO2_BRIDGE_H -#define __CIO2_BRIDGE_H - -#include -#include - -#include "ipu3-cio2.h" - -struct i2c_client; - -#define CIO2_HID "INT343E" -#define CIO2_MAX_LANES 4 -#define MAX_NUM_LINK_FREQS 3 - -/* Values are educated guesses as we don't have a spec */ -#define CIO2_SENSOR_ROTATION_NORMAL 0 -#define CIO2_SENSOR_ROTATION_INVERTED 1 - -#define CIO2_SENSOR_CONFIG(_HID, _NR, ...) \ - (const struct cio2_sensor_config) { \ - .hid = _HID, \ - .nr_link_freqs = _NR, \ - .link_freqs = { __VA_ARGS__ } \ - } - -#define NODE_SENSOR(_HID, _PROPS) \ - (const struct software_node) { \ - .name = _HID, \ - .properties = _PROPS, \ - } - -#define NODE_PORT(_PORT, _SENSOR_NODE) \ - (const struct software_node) { \ - .name = _PORT, \ - .parent = _SENSOR_NODE, \ - } - -#define NODE_ENDPOINT(_EP, _PORT, _PROPS) \ - (const struct software_node) { \ - .name = _EP, \ - .parent = _PORT, \ - .properties = _PROPS, \ - } - -#define NODE_VCM(_TYPE) \ - (const struct software_node) { \ - .name = _TYPE, \ - } - -enum cio2_sensor_swnodes { - SWNODE_SENSOR_HID, - SWNODE_SENSOR_PORT, - SWNODE_SENSOR_ENDPOINT, - SWNODE_CIO2_PORT, - SWNODE_CIO2_ENDPOINT, - /* Must be last because it is optional / maybe empty */ - SWNODE_VCM, - SWNODE_COUNT -}; - -/* Data representation as it is in ACPI SSDB buffer */ -struct cio2_sensor_ssdb { - u8 version; - u8 sku; - u8 guid_csi2[16]; - u8 devfunction; - u8 bus; - u32 dphylinkenfuses; - u32 clockdiv; - u8 link; - u8 lanes; - u32 csiparams[10]; - u32 maxlanespeed; - u8 sensorcalibfileidx; - u8 sensorcalibfileidxInMBZ[3]; - u8 romtype; - u8 vcmtype; - u8 platforminfo; - u8 platformsubinfo; - u8 flash; - u8 privacyled; - u8 degree; - u8 mipilinkdefined; - u32 mclkspeed; - u8 controllogicid; - u8 reserved1[3]; - u8 mclkport; - u8 reserved2[13]; -} __packed; - -struct cio2_property_names { - char clock_frequency[16]; - char rotation[9]; - char orientation[12]; - char bus_type[9]; - char data_lanes[11]; - char remote_endpoint[16]; - char link_frequencies[17]; -}; - -struct cio2_node_names { - char port[7]; - char endpoint[11]; - char remote_port[7]; - char vcm[16]; -}; - -struct cio2_sensor_config { - const char *hid; - const u8 nr_link_freqs; - const u64 link_freqs[MAX_NUM_LINK_FREQS]; -}; - -struct cio2_sensor { - /* append ssdb.link(u8) in "-%u" format as suffix of HID */ - char name[ACPI_ID_LEN + 4]; - struct acpi_device *adev; - struct i2c_client *vcm_i2c_client; - - /* SWNODE_COUNT + 1 for terminating NULL */ - const struct software_node *group[SWNODE_COUNT + 1]; - struct software_node swnodes[SWNODE_COUNT]; - struct cio2_node_names node_names; - - u8 link; - u8 lanes; - u32 mclkspeed; - u32 rotation; - enum v4l2_fwnode_orientation orientation; - const char *vcm_type; - - struct cio2_property_names prop_names; - struct property_entry ep_properties[5]; - struct property_entry dev_properties[5]; - struct property_entry cio2_properties[3]; - struct software_node_ref_args local_ref[1]; - struct software_node_ref_args remote_ref[1]; - struct software_node_ref_args vcm_ref[1]; -}; - -struct cio2_bridge { - struct device *dev; - int (*parse_sensor_fwnode)(struct acpi_device *adev, - struct cio2_sensor *sensor, - const struct cio2_sensor_config *cfg); - const struct cio2_sensor_config *supported_sensors; - char cio2_node_name[ACPI_ID_LEN]; - struct software_node cio2_hid_node; - u32 data_lanes[4]; - unsigned int n_sensors; - struct cio2_sensor sensors[CIO2_NUM_PORTS]; -}; - -#endif diff --git a/include/media/intel-cio2-bridge.h b/include/media/intel-cio2-bridge.h new file mode 100644 index 000000000000..f538e222c850 --- /dev/null +++ b/include/media/intel-cio2-bridge.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Author: Dan Scally */ +/* Author: Hans de Goede */ +#ifndef _INTEL_CIO2_BRIDGE_H +#define _INTEL_CIO2_BRIDGE_H + +#include +#include + +#include + +struct acpi_device; +struct i2c_client; + +#define INTEL_CIO2_HID "INT343E" +#define INTEL_CIO2_MAX_LANES 4 +#define INTEL_CIO2_NUM_PORTS 4U /* DPHYs */ +#define INTEL_CIO2_MAX_NUM_LINK_FREQS 3 + +enum intel_cio2_sensor_swnodes { + SWNODE_SENSOR_HID, + SWNODE_SENSOR_PORT, + SWNODE_SENSOR_ENDPOINT, + SWNODE_CIO2_PORT, + SWNODE_CIO2_ENDPOINT, + /* Must be last because it is optional / maybe empty */ + SWNODE_VCM, + SWNODE_COUNT +}; + +struct intel_cio2_property_names { + char clock_frequency[16]; + char rotation[9]; + char orientation[12]; + char bus_type[9]; + char data_lanes[11]; + char remote_endpoint[16]; + char link_frequencies[17]; +}; + +struct intel_cio2_node_names { + char port[7]; + char endpoint[11]; + char remote_port[7]; + char vcm[16]; +}; + +struct intel_cio2_sensor_config { + const char *hid; + const u8 nr_link_freqs; + const u64 link_freqs[INTEL_CIO2_MAX_NUM_LINK_FREQS]; +}; + +struct intel_cio2_sensor { + /* append link(u8) in "-%u" format as suffix of HID */ + char name[ACPI_ID_LEN + 4]; + struct acpi_device *adev; + struct i2c_client *vcm_i2c_client; + + /* SWNODE_COUNT + 1 for terminating NULL */ + const struct software_node *group[SWNODE_COUNT + 1]; + struct software_node swnodes[SWNODE_COUNT]; + struct intel_cio2_node_names node_names; + + u8 link; + u8 lanes; + u32 mclkspeed; + u32 rotation; + enum v4l2_fwnode_orientation orientation; + const char *vcm_type; + + struct intel_cio2_property_names prop_names; + struct property_entry ep_properties[5]; + struct property_entry dev_properties[5]; + struct property_entry cio2_properties[3]; + struct software_node_ref_args local_ref[1]; + struct software_node_ref_args remote_ref[1]; + struct software_node_ref_args vcm_ref[1]; +}; + +struct intel_cio2_bridge { + struct device *dev; + int (*parse_sensor_fwnode)(struct acpi_device *adev, + struct intel_cio2_sensor *sensor, + const struct intel_cio2_sensor_config *cfg); + const struct intel_cio2_sensor_config *supported_sensors; + char cio2_node_name[ACPI_ID_LEN]; + struct software_node cio2_hid_node; + u32 data_lanes[INTEL_CIO2_MAX_LANES]; + unsigned int n_sensors; + struct intel_cio2_sensor sensors[INTEL_CIO2_NUM_PORTS]; +}; + +int intel_cio2_bridge_init( + struct device *dev, + int (*parse_sensor_fwnode)(struct acpi_device *adev, + struct intel_cio2_sensor *sensor, + const struct intel_cio2_sensor_config *cfg), + const struct intel_cio2_sensor_config *supported_sensors); + +enum v4l2_fwnode_orientation +intel_cio2_bridge_get_orientation(struct acpi_device *adev); + +#endif From patchwork Tue Jun 27 17:56:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 13294878 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D7E50EB64D9 for ; Tue, 27 Jun 2023 17:58:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231837AbjF0R6X (ORCPT ); Tue, 27 Jun 2023 13:58:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37878 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230221AbjF0R6W (ORCPT ); Tue, 27 Jun 2023 13:58:22 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2F64E2D45 for ; Tue, 27 Jun 2023 10:57:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1687888627; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7KcVneI8yiB62H/2fkY2fRu7XIFHRBwGSRG0nnWSHlE=; b=F8US0RaMjh2ZRGpBK8YQOs0ycKnPXFDBZEfjOXuVhSn6ppPbO6uNXp0JF1cTY9lVHLPNdM bCMmMXLrNX7VZLqkkCi4v6XdCobGws3pGA75U9YOrC0vHd1SB9U+L0rZlfZCL84+8VIByu RG8DiEHxGLTfGw/4l19FQu0O7CbhjbE= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-507-urXnCjLyOFeyugiPQVpS7g-1; Tue, 27 Jun 2023 13:57:01 -0400 X-MC-Unique: urXnCjLyOFeyugiPQVpS7g-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 0CAB98ED60B; Tue, 27 Jun 2023 17:57:01 +0000 (UTC) Received: from shalem.redhat.com (unknown [10.39.194.24]) by smtp.corp.redhat.com (Postfix) with ESMTP id 63D70200A3AD; Tue, 27 Jun 2023 17:56:59 +0000 (UTC) From: Hans de Goede To: Sakari Ailus , Laurent Pinchart , Daniel Scally Cc: Hans de Goede , Mauro Carvalho Chehab , Andy Shevchenko , Kate Hsuan , Hao Yao , Bingbu Cao , linux-media@vger.kernel.org Subject: [PATCH 10/12] media: atomisp: csi2-bridge: Switch to new common cio2_bridge_init() Date: Tue, 27 Jun 2023 19:56:40 +0200 Message-ID: <20230627175643.114778-11-hdegoede@redhat.com> In-Reply-To: <20230627175643.114778-1-hdegoede@redhat.com> References: <20230627175643.114778-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Remove the duplicate csi2/cio2 ACPI bridge code and use the new common cio2_bridge_init() functionality. Signed-off-by: Hans de Goede --- drivers/staging/media/atomisp/Kconfig | 2 + .../staging/media/atomisp/pci/atomisp_csi2.h | 67 ---- .../media/atomisp/pci/atomisp_csi2_bridge.c | 307 +++--------------- include/media/intel-cio2-bridge.h | 1 + 4 files changed, 43 insertions(+), 334 deletions(-) diff --git a/drivers/staging/media/atomisp/Kconfig b/drivers/staging/media/atomisp/Kconfig index e9b168ba97bf..1103a5b30074 100644 --- a/drivers/staging/media/atomisp/Kconfig +++ b/drivers/staging/media/atomisp/Kconfig @@ -13,10 +13,12 @@ config VIDEO_ATOMISP tristate "Intel Atom Image Signal Processor Driver" depends on VIDEO_DEV && INTEL_ATOMISP depends on PMIC_OPREGION + depends on I2C select V4L2_FWNODE select IOSF_MBI select VIDEOBUF2_VMALLOC select VIDEO_V4L2_SUBDEV_API + select INTEL_CIO2_BRIDGE help Say Y here if your platform supports Intel Atom SoC camera imaging subsystem. diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2.h b/drivers/staging/media/atomisp/pci/atomisp_csi2.h index 16ddb3ab2963..8a112acba1e0 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2.h +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2.h @@ -30,9 +30,6 @@ #define CSI2_PAD_SOURCE 1 #define CSI2_PADS_NUM 2 -#define CSI2_MAX_LANES 4 -#define CSI2_MAX_LINK_FREQS 3 - #define CSI2_MAX_ACPI_GPIOS 2u struct acpi_device; @@ -55,70 +52,6 @@ struct atomisp_csi2_acpi_gpio_parsing_data { unsigned int map_count; }; -enum atomisp_csi2_sensor_swnodes { - SWNODE_SENSOR, - SWNODE_SENSOR_PORT, - SWNODE_SENSOR_ENDPOINT, - SWNODE_CSI2_PORT, - SWNODE_CSI2_ENDPOINT, - SWNODE_COUNT -}; - -struct atomisp_csi2_property_names { - char clock_frequency[16]; - char rotation[9]; - char bus_type[9]; - char data_lanes[11]; - char remote_endpoint[16]; - char link_frequencies[17]; -}; - -struct atomisp_csi2_node_names { - char port[7]; - char endpoint[11]; - char remote_port[7]; -}; - -struct atomisp_csi2_sensor_config { - const char *hid; - int lanes; - int nr_link_freqs; - u64 link_freqs[CSI2_MAX_LINK_FREQS]; -}; - -struct atomisp_csi2_sensor { - /* Append port in "-%u" format as suffix of HID */ - char name[ACPI_ID_LEN + 4]; - struct acpi_device *adev; - int port; - int lanes; - - /* SWNODE_COUNT + 1 for terminating NULL */ - const struct software_node *group[SWNODE_COUNT + 1]; - struct software_node swnodes[SWNODE_COUNT]; - struct atomisp_csi2_node_names node_names; - struct atomisp_csi2_property_names prop_names; - /* "clock-frequency", "rotation" + terminating entry */ - struct property_entry dev_properties[3]; - /* "bus-type", "data-lanes", "remote-endpoint" + "link-freq" + terminating entry */ - struct property_entry ep_properties[5]; - /* "data-lanes", "remote-endpoint" + terminating entry */ - struct property_entry csi2_properties[3]; - struct software_node_ref_args local_ref[1]; - struct software_node_ref_args remote_ref[1]; - struct software_node_ref_args vcm_ref[1]; - /* GPIO mappings storage */ - struct atomisp_csi2_acpi_gpio_map gpio_map; -}; - -struct atomisp_csi2_bridge { - struct software_node csi2_node; - char csi2_node_name[14]; - u32 data_lanes[CSI2_MAX_LANES]; - unsigned int n_sensors; - struct atomisp_csi2_sensor sensors[ATOMISP_CAMERA_NR_PORTS]; -}; - struct atomisp_mipi_csi2_device { struct v4l2_subdev subdev; struct media_pad pads[CSI2_PADS_NUM]; diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c index 71be5b1c31f2..c37c517d35eb 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c @@ -14,31 +14,14 @@ #include #include #include + +#include #include #include "atomisp_cmd.h" #include "atomisp_csi2.h" #include "atomisp_internal.h" -#define NODE_SENSOR(_HID, _PROPS) \ - ((const struct software_node) { \ - .name = _HID, \ - .properties = _PROPS, \ - }) - -#define NODE_PORT(_PORT, _SENSOR_NODE) \ - ((const struct software_node) { \ - .name = _PORT, \ - .parent = _SENSOR_NODE, \ - }) - -#define NODE_ENDPOINT(_EP, _PORT, _PROPS) \ - ((const struct software_node) { \ - .name = _EP, \ - .parent = _PORT, \ - .properties = _PROPS, \ - }) - #define PMC_CLK_RATE_19_2MHZ 19200000 /* @@ -91,7 +74,7 @@ static const guid_t atomisp_dsm_guid = * or which have not yet been converted to work without atomisp_gmin * power-management and with v4l2-async probing. */ -static const struct atomisp_csi2_sensor_config supported_sensors[] = { +static const struct intel_cio2_sensor_config supported_sensors[] = { /* GalaxyCore GC0310 */ { "INT0310", 1 }, /* Omnivision OV2680 */ @@ -402,8 +385,7 @@ static int atomisp_csi2_handle_acpi_gpio_res(struct acpi_resource *ares, void *_ * the INT3472 discrete.c code and there is some overlap, but there are * enough differences that it is difficult to share the code. */ -static int atomisp_csi2_add_gpio_mappings(struct atomisp_csi2_sensor *sensor, - struct acpi_device *adev) +static int atomisp_csi2_add_gpio_mappings(struct acpi_device *adev) { struct atomisp_csi2_acpi_gpio_parsing_data data = { }; LIST_HEAD(resource_list); @@ -471,9 +453,12 @@ static int atomisp_csi2_add_gpio_mappings(struct atomisp_csi2_sensor *sensor, } } + data.map = kzalloc(sizeof(*data.map), GFP_KERNEL); + if (!data.map) + return -ENOMEM; + /* Now parse the ACPI resources and build the lookup table */ data.adev = adev; - data.map = &sensor->gpio_map; ret = acpi_dev_get_resources(adev, &resource_list, atomisp_csi2_handle_acpi_gpio_res, &data); if (ret < 0) @@ -493,220 +478,52 @@ static int atomisp_csi2_add_gpio_mappings(struct atomisp_csi2_sensor *sensor, return ret; } -static const struct atomisp_csi2_property_names prop_names = { - .clock_frequency = "clock-frequency", - .rotation = "rotation", - .bus_type = "bus-type", - .data_lanes = "data-lanes", - .remote_endpoint = "remote-endpoint", - .link_frequencies = "link-frequencies", -}; - -static void atomisp_csi2_create_fwnode_properties(struct atomisp_csi2_sensor *sensor, - struct atomisp_csi2_bridge *bridge, - const struct atomisp_csi2_sensor_config *cfg) +static int atomisp_csi2_parse_sensor_fwnode( + struct acpi_device *adev, + struct intel_cio2_sensor *sensor, + const struct intel_cio2_sensor_config *cfg) { - sensor->prop_names = prop_names; - - sensor->local_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_CSI2_ENDPOINT]); - sensor->remote_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_SENSOR_ENDPOINT]); - - sensor->dev_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.clock_frequency, - PMC_CLK_RATE_19_2MHZ); - sensor->dev_properties[1] = PROPERTY_ENTRY_U32(sensor->prop_names.rotation, 0); - - sensor->ep_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.bus_type, - V4L2_FWNODE_BUS_TYPE_CSI2_DPHY); - sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes, - bridge->data_lanes, - sensor->lanes); - sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint, - sensor->local_ref); - if (cfg->nr_link_freqs > 0) - sensor->ep_properties[3] = - PROPERTY_ENTRY_U64_ARRAY_LEN(sensor->prop_names.link_frequencies, - cfg->link_freqs, cfg->nr_link_freqs); - - sensor->csi2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes, - bridge->data_lanes, - sensor->lanes); - sensor->csi2_properties[1] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint, - sensor->remote_ref); -} - -static void atomisp_csi2_init_swnode_names(struct atomisp_csi2_sensor *sensor) -{ - snprintf(sensor->node_names.remote_port, - sizeof(sensor->node_names.remote_port), - SWNODE_GRAPH_PORT_NAME_FMT, sensor->port); - snprintf(sensor->node_names.port, - sizeof(sensor->node_names.port), - SWNODE_GRAPH_PORT_NAME_FMT, 0); /* Always port 0 */ - snprintf(sensor->node_names.endpoint, - sizeof(sensor->node_names.endpoint), - SWNODE_GRAPH_ENDPOINT_NAME_FMT, 0); /* And endpoint 0 */ -} - -static void atomisp_csi2_init_swnode_group(struct atomisp_csi2_sensor *sensor) -{ - struct software_node *nodes = sensor->swnodes; - - sensor->group[SWNODE_SENSOR] = &nodes[SWNODE_SENSOR]; - sensor->group[SWNODE_SENSOR_PORT] = &nodes[SWNODE_SENSOR_PORT]; - sensor->group[SWNODE_SENSOR_ENDPOINT] = &nodes[SWNODE_SENSOR_ENDPOINT]; - sensor->group[SWNODE_CSI2_PORT] = &nodes[SWNODE_CSI2_PORT]; - sensor->group[SWNODE_CSI2_ENDPOINT] = &nodes[SWNODE_CSI2_ENDPOINT]; -} - -static void atomisp_csi2_create_connection_swnodes(struct atomisp_csi2_bridge *bridge, - struct atomisp_csi2_sensor *sensor) -{ - struct software_node *nodes = sensor->swnodes; - - atomisp_csi2_init_swnode_names(sensor); - - nodes[SWNODE_SENSOR] = NODE_SENSOR(sensor->name, - sensor->dev_properties); - nodes[SWNODE_SENSOR_PORT] = NODE_PORT(sensor->node_names.port, - &nodes[SWNODE_SENSOR]); - nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint, - &nodes[SWNODE_SENSOR_PORT], - sensor->ep_properties); - nodes[SWNODE_CSI2_PORT] = NODE_PORT(sensor->node_names.remote_port, - &bridge->csi2_node); - nodes[SWNODE_CSI2_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint, - &nodes[SWNODE_CSI2_PORT], - sensor->csi2_properties); - - atomisp_csi2_init_swnode_group(sensor); -} - -static void atomisp_csi2_unregister_sensors(struct atomisp_csi2_bridge *bridge) -{ - struct atomisp_csi2_sensor *sensor; - unsigned int i; - - for (i = 0; i < bridge->n_sensors; i++) { - sensor = &bridge->sensors[i]; - software_node_unregister_node_group(sensor->group); - acpi_dev_remove_driver_gpios(sensor->adev); - acpi_dev_put(sensor->adev); - } -} - -static int atomisp_csi2_connect_sensor(const struct atomisp_csi2_sensor_config *cfg, - struct atomisp_csi2_bridge *bridge, - struct atomisp_device *isp) -{ - struct fwnode_handle *fwnode, *primary; - struct atomisp_csi2_sensor *sensor; - struct acpi_device *adev; int ret, clock_num; - for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { - if (!adev->status.enabled) - continue; + /* + * ACPI takes care of turning the PMC clock on and off, but on BYT + * the clock defaults to 25 MHz instead of the expected 19.2 MHz. + * Get the PMC-clock number from ACPI PR0 method and set it to 19.2 MHz. + * The PMC-clock number is also used to determine the default CSI port. + */ + clock_num = atomisp_csi2_get_pmc_clk_nr_from_acpi_pr0(adev); - if (bridge->n_sensors >= ATOMISP_CAMERA_NR_PORTS) { - dev_err(isp->dev, "Exceeded available CSI2 ports\n"); - ret = -EOVERFLOW; - goto err_put_adev; - } + ret = atomisp_csi2_set_pmc_clk_freq(adev, clock_num); + if (ret) + return ret; - sensor = &bridge->sensors[bridge->n_sensors]; - - /* - * ACPI takes care of turning the PMC clock on and off, but on BYT - * the clock defaults to 25 MHz instead of the expected 19.2 MHz. - * Get the PMC-clock number from ACPI _PR0 method and set it to 19.2 MHz. - * The PMC-clock number is also used to determine the default CSI port. - */ - clock_num = atomisp_csi2_get_pmc_clk_nr_from_acpi_pr0(adev); - - ret = atomisp_csi2_set_pmc_clk_freq(adev, clock_num); - if (ret) - goto err_put_adev; - - sensor->port = atomisp_csi2_get_port(adev, clock_num); - if (sensor->port >= ATOMISP_CAMERA_NR_PORTS) { - acpi_handle_err(adev->handle, "Invalid port: %d\n", sensor->port); - ret = -EINVAL; - goto err_put_adev; - } - - sensor->lanes = gmin_cfg_get_int(adev, "CsiLanes", cfg->lanes); - if (sensor->lanes > CSI2_MAX_LANES) { - acpi_handle_err(adev->handle, "Invalid number of lanes: %d\n", sensor->lanes); - ret = -EINVAL; - goto err_put_adev; - } - - ret = atomisp_csi2_add_gpio_mappings(sensor, adev); - if (ret) - goto err_put_adev; - - snprintf(sensor->name, sizeof(sensor->name), "%s-%u", - cfg->hid, sensor->port); - - atomisp_csi2_create_fwnode_properties(sensor, bridge, cfg); - atomisp_csi2_create_connection_swnodes(bridge, sensor); - - ret = software_node_register_node_group(sensor->group); - if (ret) - goto err_remove_mappings; - - fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_SENSOR]); - if (!fwnode) { - ret = -ENODEV; - goto err_free_swnodes; - } - - sensor->adev = acpi_dev_get(adev); - - primary = acpi_fwnode_handle(adev); - primary->secondary = fwnode; - - bridge->n_sensors++; + sensor->link = atomisp_csi2_get_port(adev, clock_num); + if (sensor->link >= ATOMISP_CAMERA_NR_PORTS) { + dev_err(&adev->dev, "Invalid port: %u\n", sensor->link); + return -EINVAL; } - return 0; - -err_free_swnodes: - software_node_unregister_node_group(sensor->group); -err_remove_mappings: - acpi_dev_remove_driver_gpios(adev); -err_put_adev: - acpi_dev_put(adev); - return ret; -} - -static int atomisp_csi2_connect_sensors(struct atomisp_csi2_bridge *bridge, - struct atomisp_device *isp) -{ - unsigned int i; - int ret; - - for (i = 0; i < ARRAY_SIZE(supported_sensors); i++) { - const struct atomisp_csi2_sensor_config *cfg = &supported_sensors[i]; - - ret = atomisp_csi2_connect_sensor(cfg, bridge, isp); - if (ret) - goto err_unregister_sensors; + sensor->lanes = gmin_cfg_get_int(adev, "CsiLanes", cfg->default_lanes); + if (sensor->lanes > INTEL_CIO2_MAX_LANES) { + dev_err(&adev->dev, "Invalid lane-count: %d\n", sensor->lanes); + return -EINVAL; } - return 0; + ret = atomisp_csi2_add_gpio_mappings(adev); + if (ret) + return ret; -err_unregister_sensors: - atomisp_csi2_unregister_sensors(bridge); - return ret; + sensor->mclkspeed = PMC_CLK_RATE_19_2MHZ; + sensor->rotation = 0; + sensor->orientation = V4L2_FWNODE_ORIENTATION_EXTERNAL; + + return 0; } int atomisp_csi2_bridge_init(struct atomisp_device *isp) { - struct atomisp_csi2_bridge *bridge; struct device *dev = isp->dev; struct fwnode_handle *fwnode; - int i, ret; /* * This function is intended to run only once and then leave @@ -718,52 +535,8 @@ int atomisp_csi2_bridge_init(struct atomisp_device *isp) if (fwnode && fwnode->secondary) return 0; - bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); - if (!bridge) - return -ENOMEM; - - strscpy(bridge->csi2_node_name, "atomisp-csi2", sizeof(bridge->csi2_node_name)); - bridge->csi2_node.name = bridge->csi2_node_name; - - ret = software_node_register(&bridge->csi2_node); - if (ret < 0) { - dev_err(dev, "Failed to register the CSI2 HID node\n"); - goto err_free_bridge; - } - - /* - * Map the lane arrangement, which is fixed for the ISP2 (meaning we - * only need one, rather than one per sensor). We include it as a - * member of the bridge struct rather than a global variable so - * that it survives if the module is unloaded along with the rest of - * the struct. - */ - for (i = 0; i < CSI2_MAX_LANES; i++) - bridge->data_lanes[i] = i + 1; - - ret = atomisp_csi2_connect_sensors(bridge, isp); - if (ret || bridge->n_sensors == 0) - goto err_unregister_csi2; - - fwnode = software_node_fwnode(&bridge->csi2_node); - if (!fwnode) { - dev_err(dev, "Error getting fwnode from csi2 software_node\n"); - ret = -ENODEV; - goto err_unregister_sensors; - } - - set_secondary_fwnode(dev, fwnode); - - return 0; - -err_unregister_sensors: - atomisp_csi2_unregister_sensors(bridge); -err_unregister_csi2: - software_node_unregister(&bridge->csi2_node); -err_free_bridge: - kfree(bridge); - - return ret; + return intel_cio2_bridge_init(dev, atomisp_csi2_parse_sensor_fwnode, + supported_sensors); } /******* V4L2 sub-device asynchronous registration callbacks***********/ diff --git a/include/media/intel-cio2-bridge.h b/include/media/intel-cio2-bridge.h index f538e222c850..90fde180faef 100644 --- a/include/media/intel-cio2-bridge.h +++ b/include/media/intel-cio2-bridge.h @@ -47,6 +47,7 @@ struct intel_cio2_node_names { struct intel_cio2_sensor_config { const char *hid; + const u8 default_lanes; const u8 nr_link_freqs; const u64 link_freqs[INTEL_CIO2_MAX_NUM_LINK_FREQS]; }; From patchwork Tue Jun 27 17:56:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 13294880 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D58D3EB64DC for ; Tue, 27 Jun 2023 17:58:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231867AbjF0R60 (ORCPT ); Tue, 27 Jun 2023 13:58:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37922 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231696AbjF0R6X (ORCPT ); Tue, 27 Jun 2023 13:58:23 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AE62D30DA for ; Tue, 27 Jun 2023 10:57:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1687888626; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=kYbzLaH2jVeq5v43JT+7cqrn5RHT3y2f4UHhPLIIFQY=; b=RYJOP9if6mq12+GxLG7zvLrVb8UzU9doo8ACsmDymFhJP1FBqwOj7mqwM6s/HVfSSXsf6P Qm2s6HTlQlCgN2QlOTuegKbC29jYPDYlBnx88kq84gDWWGO9dFVVNH09iH4XxoJfky7e69 ohsBFujZYdV+gccF7kO5j6FKSWGAqEg= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-187-nfO2pKnBMqiO32alBH2Gyg-1; Tue, 27 Jun 2023 13:57:03 -0400 X-MC-Unique: nfO2pKnBMqiO32alBH2Gyg-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 8E055858EED; Tue, 27 Jun 2023 17:57:02 +0000 (UTC) Received: from shalem.redhat.com (unknown [10.39.194.24]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3E96D200A3AD; Tue, 27 Jun 2023 17:57:01 +0000 (UTC) From: Hans de Goede To: Sakari Ailus , Laurent Pinchart , Daniel Scally Cc: Hans de Goede , Mauro Carvalho Chehab , Andy Shevchenko , Kate Hsuan , Hao Yao , Bingbu Cao , linux-media@vger.kernel.org Subject: [PATCH 11/12] media: intel-cio2-bridge: Add a runtime-pm device-link between VCM and sensor Date: Tue, 27 Jun 2023 19:56:41 +0200 Message-ID: <20230627175643.114778-12-hdegoede@redhat.com> In-Reply-To: <20230627175643.114778-1-hdegoede@redhat.com> References: <20230627175643.114778-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org In most cases when a VCM is used there is a single integrated module with the sensor + VCM + lens. This means that the sensor and VCM often share regulators and possibly also something like a powerdown pin. In the ACPI tables this is modelled as a single ACPI device with multiple I2cSerialBus resources. On atomisp devices the regulators and clks are modelled as ACPI power-resources, which are controlled by the (ACPI) power state of the sensor. So the sensor must be in D0 power state for the VCM to work. To make this work add a device-link with DL_FLAG_PM_RUNTIME flag so that the sensor will automatically be runtime-resumed whenever the VCM is runtime-resumed. This requires the probing of the VCM and thus the creation of the VCM I2C-client to be delayed till after the sensor driver has bound. Move the instantiation of the VCM I2C-client to the v4l2_async_notifier bound op, so that it is done after the sensor driver has bound; and add code to add the device-link. This fixes the problem with the shared ACPI power-resources on atomisp2 and this avoids the need for VCM related workarounds on IPU3. E.g. until now the dw9719 driver needed to get and control a Vsio (V sensor IO) regulator since that needs to be enabled to enable I2C pass-through on the PMIC on the sensor module. So the driver was controlling this regulator even though the actual dw9719 chip has no Vsio pin / power-plane. This also removes the need for intel_cio2_bridge_init() to return -EPROBE_DEFER since the VCM is now instantiated later. Signed-off-by: Hans de Goede --- drivers/media/common/intel-cio2-bridge.c | 160 +++++++++++------- drivers/media/pci/intel/ipu3/ipu3-cio2-main.c | 5 + drivers/media/pci/intel/ipu3/ipu3-cio2.h | 3 + include/media/intel-cio2-bridge.h | 4 +- 4 files changed, 111 insertions(+), 61 deletions(-) diff --git a/drivers/media/common/intel-cio2-bridge.c b/drivers/media/common/intel-cio2-bridge.c index 2f4256f9152c..997581bcc3b9 100644 --- a/drivers/media/common/intel-cio2-bridge.c +++ b/drivers/media/common/intel-cio2-bridge.c @@ -5,7 +5,9 @@ #include #include #include +#include #include +#include #include #include @@ -189,30 +191,111 @@ static void cio2_bridge_create_connection_swnodes( cio2_bridge_init_swnode_group(sensor); } -static void cio2_bridge_instantiate_vcm_i2c_client( - struct intel_cio2_sensor *sensor) -{ - struct i2c_board_info board_info = { }; +/* + * The actual instantiation must be done from a workqueue to avoid + * a deadlock on taking list_lock from v4l2-async twice. + */ +struct intel_cio2_bridge_instantiate_vcm_work_data { + struct work_struct work; + struct device *sensor; char name[16]; + struct i2c_board_info board_info; +}; - if (!sensor->vcm_type) - return; +static void intel_cio2_bridge_instantiate_vcm_work(struct work_struct *_work) +{ + struct intel_cio2_bridge_instantiate_vcm_work_data *work = + container_of(_work, + struct intel_cio2_bridge_instantiate_vcm_work_data, + work); + struct acpi_device *adev = ACPI_COMPANION(work->sensor); + struct i2c_client *vcm_client; + bool put_fwnode = true; + int ret; - snprintf(name, sizeof(name), "%s-VCM", acpi_dev_name(sensor->adev)); - board_info.dev_name = name; - strscpy(board_info.type, sensor->vcm_type, ARRAY_SIZE(board_info.type)); - board_info.swnode = &sensor->swnodes[SWNODE_VCM]; - - sensor->vcm_i2c_client = - i2c_acpi_new_device_by_fwnode(acpi_fwnode_handle(sensor->adev), - 1, &board_info); - if (IS_ERR(sensor->vcm_i2c_client)) { - dev_warn(&sensor->adev->dev, "Error instantiation VCM i2c-client: %ld\n", - PTR_ERR(sensor->vcm_i2c_client)); - sensor->vcm_i2c_client = NULL; + /* + * The client may get probed before the device_link gets added below + * make sure the sensor is powered-up during probe. + */ + ret = pm_runtime_get_sync(work->sensor); + if (ret < 0) { + dev_err(work->sensor, "Error %d runtime-resuming sensor, cannot instantiate VCM\n", + ret); + goto out; } + + /* + * Note the client is created only once and then kept around + * even after a rmmod, just like the software-nodes. + */ + vcm_client = i2c_acpi_new_device_by_fwnode(acpi_fwnode_handle(adev), + 1, &work->board_info); + if (IS_ERR(vcm_client)) { + dev_err(work->sensor, "Error instantiating VCM client: %ld\n", + PTR_ERR(vcm_client)); + goto out; + } + + device_link_add(&vcm_client->dev, work->sensor, DL_FLAG_PM_RUNTIME); + + dev_info(work->sensor, "Instantiated %s VCM\n", work->board_info.type); + put_fwnode = false; /* Ownership has passed to the i2c-client */ + +out: + pm_runtime_put(work->sensor); + put_device(work->sensor); + if (put_fwnode) + fwnode_handle_put(work->board_info.fwnode); + kfree(work); } +int intel_cio2_bridge_instantiate_vcm(struct device *sensor) +{ + struct intel_cio2_bridge_instantiate_vcm_work_data *work; + struct acpi_device *adev = ACPI_COMPANION(sensor); + struct fwnode_handle *vcm_fwnode; + struct i2c_client *vcm_client; + char *sep; + + if (!adev) + return 0; + + vcm_fwnode = fwnode_find_reference(dev_fwnode(sensor), "lens-focus", 0); + if (IS_ERR(vcm_fwnode)) + return 0; + + /* When reloading modules the client will already exist */ + vcm_client = i2c_find_device_by_fwnode(vcm_fwnode); + if (vcm_client) { + fwnode_handle_put(vcm_fwnode); + put_device(&vcm_client->dev); + return 0; + } + + work = kzalloc(sizeof(*work), GFP_KERNEL); + if (!work) { + fwnode_handle_put(vcm_fwnode); + return -ENOMEM; + } + + INIT_WORK(&work->work, intel_cio2_bridge_instantiate_vcm_work); + work->sensor = get_device(sensor); + snprintf(work->name, sizeof(work->name), "%s-VCM", + acpi_dev_name(adev)); + work->board_info.dev_name = work->name; + work->board_info.fwnode = vcm_fwnode; + strscpy(work->board_info.type, fwnode_get_name(vcm_fwnode), + I2C_NAME_SIZE); + /* Strip "-" postfix */ + sep = strchrnul(work->board_info.type, '-'); + *sep = 0; + + queue_work(system_long_wq, &work->work); + + return 0; +} +EXPORT_SYMBOL(intel_cio2_bridge_instantiate_vcm); + static void cio2_bridge_unregister_sensors(struct intel_cio2_bridge *bridge) { struct intel_cio2_sensor *sensor; @@ -222,7 +305,6 @@ static void cio2_bridge_unregister_sensors(struct intel_cio2_bridge *bridge) sensor = &bridge->sensors[i]; software_node_unregister_node_group(sensor->group); acpi_dev_put(sensor->adev); - i2c_unregister_device(sensor->vcm_i2c_client); } } @@ -273,8 +355,6 @@ static int cio2_bridge_connect_sensor( primary = acpi_fwnode_handle(adev); primary->secondary = fwnode; - cio2_bridge_instantiate_vcm_i2c_client(sensor); - dev_info(bridge->dev, "Found supported sensor %s\n", acpi_dev_name(adev)); @@ -311,41 +391,6 @@ static int cio2_bridge_connect_sensors(struct intel_cio2_bridge *bridge) return ret; } -/* - * The VCM cannot be probed until the PMIC is completely setup. We cannot rely - * on -EPROBE_DEFER for this, since the consumer<->supplier relations between - * the VCM and regulators/clks are not described in ACPI, instead they are - * passed as board-data to the PMIC drivers. Since -PROBE_DEFER does not work - * for the clks/regulators the VCM i2c-clients must not be instantiated until - * the PMIC is fully setup. - * - * The sensor/VCM ACPI device has an ACPI _DEP on the PMIC, check this using the - * acpi_dev_ready_for_enumeration() helper, like the i2c-core-acpi code does - * for the sensors. - */ -static int cio2_bridge_sensors_are_ready( - const struct intel_cio2_sensor_config *supported_sensors) -{ - struct acpi_device *adev; - bool ready = true; - unsigned int i; - - for (i = 0; supported_sensors[i].hid; i++) { - const struct intel_cio2_sensor_config *cfg = - &supported_sensors[i]; - - for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { - if (!adev->status.enabled) - continue; - - if (!acpi_dev_ready_for_enumeration(adev)) - ready = false; - } - } - - return ready; -} - int intel_cio2_bridge_init( struct device *dev, int (*parse_sensor_fwnode)(struct acpi_device *adev, @@ -358,9 +403,6 @@ int intel_cio2_bridge_init( unsigned int i; int ret; - if (!cio2_bridge_sensors_are_ready(supported_sensors)) - return -EPROBE_DEFER; - bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); if (!bridge) return -ENOMEM; diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c index afc3255b5eb8..a22d213d66e9 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c @@ -1386,10 +1386,15 @@ static int cio2_notifier_bound(struct v4l2_async_notifier *notifier, struct cio2_device *cio2 = to_cio2_device(notifier); struct sensor_async_subdev *s_asd = to_sensor_asd(asd); struct cio2_queue *q; + int ret; if (cio2->queue[s_asd->csi2.port].sensor) return -EBUSY; + ret = intel_cio2_bridge_instantiate_vcm(sd->dev); + if (ret) + return ret; + q = &cio2->queue[s_asd->csi2.port]; q->csi2 = s_asd->csi2; diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.h b/drivers/media/pci/intel/ipu3/ipu3-cio2.h index 7ff7915f9823..208d60364f44 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.h +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.h @@ -12,6 +12,7 @@ #include +#include #include #include #include @@ -463,6 +464,8 @@ static inline struct cio2_queue *vb2q_to_cio2_queue(struct vb2_queue *vq) int cio2_bridge_init(struct device *dev); #else static inline int cio2_bridge_init(struct device *dev) { return 0; } +static inline int +intel_cio2_bridge_instantiate_vcm(struct device *dev) { return 0; } #endif #endif diff --git a/include/media/intel-cio2-bridge.h b/include/media/intel-cio2-bridge.h index 90fde180faef..faa60a5b1cd8 100644 --- a/include/media/intel-cio2-bridge.h +++ b/include/media/intel-cio2-bridge.h @@ -10,7 +10,6 @@ #include struct acpi_device; -struct i2c_client; #define INTEL_CIO2_HID "INT343E" #define INTEL_CIO2_MAX_LANES 4 @@ -56,7 +55,6 @@ struct intel_cio2_sensor { /* append link(u8) in "-%u" format as suffix of HID */ char name[ACPI_ID_LEN + 4]; struct acpi_device *adev; - struct i2c_client *vcm_i2c_client; /* SWNODE_COUNT + 1 for terminating NULL */ const struct software_node *group[SWNODE_COUNT + 1]; @@ -99,6 +97,8 @@ int intel_cio2_bridge_init( const struct intel_cio2_sensor_config *cfg), const struct intel_cio2_sensor_config *supported_sensors); +int intel_cio2_bridge_instantiate_vcm(struct device *sensor); + enum v4l2_fwnode_orientation intel_cio2_bridge_get_orientation(struct acpi_device *adev); From patchwork Tue Jun 27 17:56:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 13294879 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A2664EB64DD for ; Tue, 27 Jun 2023 17:58:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231504AbjF0R6Z (ORCPT ); Tue, 27 Jun 2023 13:58:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37972 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231588AbjF0R6X (ORCPT ); Tue, 27 Jun 2023 13:58:23 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BDEFA358A for ; Tue, 27 Jun 2023 10:57:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1687888630; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=itt6oqukh1+EnQXouEStoimfB0wBOa+JiwN4KAGdN5M=; b=SfLVe75Hfuc2ZTuqujE1DUn029YD3C+6Ia7YxZ4O2afmMoaJhWX8iW+eGFgHhH8laVFdCU cZE6EGwUCSekaZrk4DmPX7W+3rSX3LZgT2Rt+ow9t7IwT4Kn8Hb5vrRdnBByQrXUmT+b+q n7UDJfRxy+SpfGkaU6p2MhPw7Hkcj2c= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-573-eUrcKxeOMDyI3gYM2Qdk0g-1; Tue, 27 Jun 2023 13:57:06 -0400 X-MC-Unique: eUrcKxeOMDyI3gYM2Qdk0g-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 673F33C0FC9E; Tue, 27 Jun 2023 17:57:05 +0000 (UTC) Received: from shalem.redhat.com (unknown [10.39.194.24]) by smtp.corp.redhat.com (Postfix) with ESMTP id C1C91200B677; Tue, 27 Jun 2023 17:57:02 +0000 (UTC) From: Hans de Goede To: Sakari Ailus , Laurent Pinchart , Daniel Scally Cc: Hans de Goede , Mauro Carvalho Chehab , Andy Shevchenko , Kate Hsuan , Hao Yao , Bingbu Cao , linux-media@vger.kernel.org Subject: [PATCH 12/12] [RFC] media: dw9719: Drop hack to enable "vsio" regulator Date: Tue, 27 Jun 2023 19:56:42 +0200 Message-ID: <20230627175643.114778-13-hdegoede@redhat.com> In-Reply-To: <20230627175643.114778-1-hdegoede@redhat.com> References: <20230627175643.114778-1-hdegoede@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Drop the hack where the driver is getting + enabling a "vsio" regulator even though the dw9719 does not have a vsio pin / power-plane at all. Now that drivers/media/common/intel-cio2-bridge.c adds device-link making the VCM a consumer of the sensor this hack is no longer necessary. Signed-off-by: Hans de Goede --- Note to reviewers, the dw9719 driver is not upstream yet (I plan to resubmit it soon with this squashed in). This patch is only included in this patch-set to illustrate how the VCM -> sensor device-link avoids the need for hacks like this. --- drivers/media/i2c/dw9719.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/drivers/media/i2c/dw9719.c b/drivers/media/i2c/dw9719.c index 94b76b4b2463..5fe01a125c1a 100644 --- a/drivers/media/i2c/dw9719.c +++ b/drivers/media/i2c/dw9719.c @@ -35,14 +35,12 @@ #define DW9719_DEFAULT_VCM_FREQ 0x60 #define DW9719_ENABLE_RINGING 0x02 -#define NUM_REGULATORS 2 - #define to_dw9719_device(x) container_of(x, struct dw9719_device, sd) struct dw9719_device { struct device *dev; struct i2c_client *client; - struct regulator_bulk_data regulators[NUM_REGULATORS]; + struct regulator *regulator; struct v4l2_subdev sd; struct dw9719_v4l2_ctrls { @@ -131,14 +129,14 @@ static int dw9719_detect(struct dw9719_device *dw9719) static int dw9719_power_down(struct dw9719_device *dw9719) { - return regulator_bulk_disable(NUM_REGULATORS, dw9719->regulators); + return regulator_disable(dw9719->regulator); } static int dw9719_power_up(struct dw9719_device *dw9719) { int ret; - ret = regulator_bulk_enable(NUM_REGULATORS, dw9719->regulators); + ret = regulator_enable(dw9719->regulator); if (ret) return ret; @@ -315,21 +313,10 @@ static int dw9719_probe(struct i2c_client *client) dw9719->client = client; dw9719->dev = &client->dev; - dw9719->regulators[0].supply = "vdd"; - /* - * The DW9719 has only the 1 VDD voltage input, but some PMICs such as - * the TPS68470 PMIC have I2C passthrough capability, to disconnect the - * sensor's I2C pins from the I2C bus when the sensors VSIO (Sensor-IO) - * is off, because some sensors then short these pins to ground; - * and the DW9719 might sit behind this passthrough, this it needs to - * enable VSIO as that will also enable the I2C passthrough. - */ - dw9719->regulators[1].supply = "vsio"; - - ret = devm_regulator_bulk_get(&client->dev, NUM_REGULATORS, - dw9719->regulators); - if (ret) - return dev_err_probe(&client->dev, ret, "getting regulators\n"); + dw9719->regulator = devm_regulator_get(&client->dev, "vdd"); + if (IS_ERR(dw9719->regulator)) + return dev_err_probe(&client->dev, PTR_ERR(dw9719->regulator), + "getting regulator\n"); v4l2_i2c_subdev_init(&dw9719->sd, client, &dw9719_ops); dw9719->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;