From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 808C0410D3D for ; Thu, 30 Jul 2026 23:48:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785455321; cv=none; b=FTGC/MI/SHR+8TZ6KvZIunrB2nm3SMICoFUkWkyQsIxxJ7KAQSGvoIuFNapQ3jC7wveI4TWtpuswIiEyERt3fk4CYQXubJgp7/o4jUN9XVV3mi1ImJcYgGsWVFhUaSX93eI812aHNBJ2K6XQSf0fh58SfMUqEfrHInZBiIB+Ss0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785455321; c=relaxed/simple; bh=wsQuQdeXxny5DqDtLdvjRx5ctTVaGE9I3JRJav7j6I8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kjoIHVUTQ3y5y84Ekvh5+o8lHgQf81lNEciRmtD7hJYw5FDSx1n3GzD5Kso6KG9vIcq+1Cuq5yfrbtiDCtC3OJEv3kh3GOp+ZLOKLcuhndzzKZTh0V/1Gzsy/xcrYAUsMBKhpeyLNRHIfad9+t4qeG5K11VIuwta3NUPR151DuU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=lHyhVmbN; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=K+LE5dad; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="lHyhVmbN"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="K+LE5dad" Received: from pps.filterd (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 66UMqvIJ2064774 for ; Thu, 30 Jul 2026 23:48:38 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= RiSMTUd439dP8/Dp6JEFU4I86JHv2MdRsiVkm4Y6TKA=; b=lHyhVmbN/acFqYvC 2xKMhOYj6cDYGWNg1BlCayLmKwwYUtUL4p8Q0XL6G0/UReod/3nVKZbsHmUGnmLN i+SWB60g0ss1knyahzjDrV8eaKzkrTseiwkR3L83lw6CV0K/IlEiHlSp7LLry2I2 LGgzuf/DHKnwB07VN9mON87Bbz7dG2/RGretK64M3tG9oN6UENPZPeVvd0gBayqe y/cUZ4TcPcmfSx8hRjAM9+qivwX79nZeDCaoukPJwzv3PaSi5JpnMDMRLeHyiET0 BKE2L4Q/A46ch+jHRAlEuPk0TQIn/1JfY/6BpNbbYBD2uhbMHKqQU8y38tal/N0Y gXEPlA== Received: from mail-qt1-f199.google.com (mail-qt1-f199.google.com [209.85.160.199]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4frfja85jd-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Thu, 30 Jul 2026 23:48:37 +0000 (GMT) Received: by mail-qt1-f199.google.com with SMTP id d75a77b69052e-51c1d30035dso2574801cf.2 for ; Thu, 30 Jul 2026 16:48:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1785455317; x=1786060117; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=RiSMTUd439dP8/Dp6JEFU4I86JHv2MdRsiVkm4Y6TKA=; b=K+LE5dad9cKWAjnxVVKT+kgus6F9T3Lz3m1XTw55cueqNHijb3fxJ0Tms5NnF/zopd ftE7NUQmO8GgpCtx/e59bymHSn4fawtWJ4PtcLi+S7ZGVDZfTjtKpYYeGCeJ4jfjL517 FVBQZQldsawA8CZfiAPZlUc5DblewPUXzuub39VHB3QRE2l2/HvWDc9brX/4ugQPXMBj NkjoF6P0mIo7ZhcsVMCPiMnOveFOLNL46aYRW901grBJl2fgrkBj5Tvl2bo4N+eteADD cPzIYFPBM6qPtiUj4Gt7DermRYaTyHqmO0zuwst7NAW2bQarixcXe9s7VScKAL8LS3B6 r9cg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785455317; x=1786060117; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=RiSMTUd439dP8/Dp6JEFU4I86JHv2MdRsiVkm4Y6TKA=; b=Z9fUoQRto5I+aAqgrPx7Fq+kQ1Q7jwo4XX2JDXCXj6kcDqYH7wVkhfahkLTXI8933Q pBh7ZhYwn7GHPqESNtJx9DIeKTIAMQn3+WzPbR/irT/uWVBs2PcIv7wSywpfQjYM5nOc 8RX88rBKT+nCpllsBmQBpJ13Foft1X5zPk5jVOQr9IrDyl6mObd7g8ipgHRdcniFGkOX 8MCmdz4uOvsmPkY/pbTOMQ8zwOfSL6D9bQB3hgxAfPtLRPmu+aKFbVzdI/PeqXnH4D7h cViewPhH8ahRewOglITDTTTwv0dTyy5/Dlu9tlsEVgfs+H1eWM7iHqWp9sMCnr+CZi3G 10+w== X-Forwarded-Encrypted: i=1; AHgh+RqBsbP7epgG49H9wNKFs+CP58+t1SsYAq8WTnvRMcPKF39cxcZtVx10bRFwtOYUvnMtK6ZkT6wCKu9LpBw=@vger.kernel.org X-Gm-Message-State: AOJu0Ywl31XHrTLFwfKZY0IEClzj4PAs4vMT2xZDjnVm77TE6dbvZCI2 gyZgvu3CPrkGczeyRJGq2OXA6SsRnEERscbq6sIv1ULc6trwDL+08Lo2aP7LMbTFgbitmmHfbaZ zMX0o71LnQePN7hjXTsEU090tZtiCJwfedHRlUzk6ztrcSoi4HdWtfGsSki62xEKPGpY= X-Gm-Gg: AR+sD13aLMDCI0LIs7dp+f4BySetepNrPbfBTU98aHAI+dacy7VTtdSylKEyEa3KzaV yD8FdAJAqZ7fUWfFIJfFLJLZD5vsdhl7KRZHka2njvBhUR4OZpDelIhzywdspxOuyMIkHFbrW+z AJHhBgavPMC+WUHI9x5ElwXpHg59AALhd+CgSWlHJUK98Hd0f1v5VX2RmsgZYBRNvrzpdg2bSjB c4TyaxsleLncZ744wNXx5LY4FRT6YhE/vfrfmnQL6OcNXNOGEW0oFCurT0K/BrVvJvtLyz37jtD YVAR66hByhPpbgmf4swWIX8j/+Mi2nmoRX/5scWcdLRZEXuT6iNeqHQy0ZXJ7v1NW8hlEWbELtA vmH3RleBxE/uCqfQ4FXWq0TDQur73+ll2ZcVXEInMYGDtlPaPLKXML/aUrTFdQgwwgGMbwaszjX SUZxay9SXNCZJluA== X-Received: by 2002:ac8:5f10:0:b0:51c:db4:3cb2 with SMTP id d75a77b69052e-52b386ae57bmr53133091cf.63.1785455316938; Thu, 30 Jul 2026 16:48:36 -0700 (PDT) X-Received: by 2002:ac8:5f10:0:b0:51c:db4:3cb2 with SMTP id d75a77b69052e-52b386ae57bmr53132771cf.63.1785455316355; Thu, 30 Jul 2026 16:48:36 -0700 (PDT) Received: from umbar.lan (2001-14ba-a073-af00-264b-feff-fe8b-be8a.rev.dnainternet.fi. [2001:14ba:a073:af00:264b:feff:fe8b:be8a]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5b2db9ba724sm634487e87.45.2026.07.30.16.48.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Jul 2026 16:48:34 -0700 (PDT) From: Dmitry Baryshkov Date: Fri, 31 Jul 2026 02:48:23 +0300 Subject: [PATCH v9 02/19] media: iris: Add Gen2 firmware autodetect and fallback Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Message-Id: <20260731-iris-ar50lt-v9-2-d71a782001c0@oss.qualcomm.com> References: <20260731-iris-ar50lt-v9-0-d71a782001c0@oss.qualcomm.com> In-Reply-To: <20260731-iris-ar50lt-v9-0-d71a782001c0@oss.qualcomm.com> To: Vikash Garodia , Abhinav Kumar , Bryan O'Donoghue , Mauro Carvalho Chehab , Bjorn Andersson , Konrad Dybcio , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Vishnu Reddy Cc: linux-media@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Dikshita Agarwal , Bryan O'Donoghue X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=17368; i=dmitry.baryshkov@oss.qualcomm.com; h=from:subject:message-id; bh=OddETrjfI6cBT0fTSRIDpKbM1AIqOJxlQaBWDV/yFBo=; b=owEBbQGS/pANAwAKAYs8ij4CKSjVAcsmYgBqa+LJjOXvSTFC2/jnE34fIevrxHCujZxueDpa+ VOi6Lk5+xKJATMEAAEKAB0WIQRMcISVXLJjVvC4lX+LPIo+Aiko1QUCamviyQAKCRCLPIo+Aiko 1bLTB/9R4Glb+v+5u34QDVYT7DCtFX/KveBMll8h5MRYghkqJmH3Hg/4vYlmKWJxI3nxEr78kbc 28iHj307bvDEokZY9wWaAtIToyK996rwalvsV8pgUaBphpNli2VMRIZxMucTz4UC1KRgmCuemUI fHhXZ2/XGlhu3ywRHRjHZx0sDxgncLcuUJ8sRdg7tGCrjNqmMoIlQccnAzEJReFnb0zxctNGn+e RTRLoZCg4A8GbfmOjyKWrX7jFYHwA1SBd+iSnQ98Tdqs976xgtTgNSTsPq1ufEjZIruNi8B4SsQ 9+KqfEIqGYOrzLltS9cNhZ9UvYsKD+uiwGVp6ADrwpnS8kyn X-Developer-Key: i=dmitry.baryshkov@oss.qualcomm.com; a=openpgp; fpr=8F88381DD5C873E4AE487DA5199BF1243632046A X-Proofpoint-ORIG-GUID: kTKNGQFuq_4ZiSHZ-R31Zew_O-CU2agf X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNzMwMDE2OCBTYWx0ZWRfX+VoTglo23HRB /GVL0Q+fZufuCIoZfl7UNtKihWKFdgBQn+hkJI/af2K940O8KxeKHF6RonGiG4QvjtKzYURbmcC s9wfhEU1W7sKBymtL339+XRiz4+APfxD0LLbxMBOy/nUFCTUsmpEuNtCyviPxSmzWjxij1wsBZ6 3I2vDgkNQ1yL/chxydweJuhzhdiWrs2gYDj/tEP2YFFtcqyBatHF/1K5FJqcvtG5xsvIEnzG9I0 3iFXiuok1WjXRhgr+2CxwTqfGnsP5+BrBK3ox31+eeYZjZIQdArd6EEvAM+gT+CTDafNZDZeKdn d5dP1U3uboZPRCLyfdFmFlkI2rAG6/SxFFByYDSE2Rs5NyEiOxgNY/02dvBfM5QEyHPb9IbT8jp 4jG3QBCxhqTYj7Ksp3yOFrkLxq07J/OwNvT8u0KZDEMp0oUtVUtVPegthCpK5pyRs1bcUuBKofj tpNCuEYpDuYpajKsI2A== X-Proofpoint-GUID: kTKNGQFuq_4ZiSHZ-R31Zew_O-CU2agf X-Proofpoint-Spam-Info: AW1haW4tMjYwNzMwMDE2OCBTYWx0ZWRfX0TKYrON/c+pm 2TscpmHmyuUfQx8shlXk4Uka1EnKcuLVlVXD6TnMAUZs0h3CRh6XmajJ5vb6clDOFm6Xncc1Cbt z8DP4n8Tbh/bf6coNQk+NYsQzoysras= X-Authority-Analysis: v=2.4 cv=XtzK/1F9 c=1 sm=1 tr=0 ts=6a6be2d5 cx=c_pps a=WeENfcodrlLV9YRTxbY/uA==:117 a=xqWC_Br6kY4A:10 a=IkcTkHD0fZMA:10 a=RAioF0-LDSMA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=yx91gb_oNiZeI1HMLzn7:22 a=EUspDBNiAAAA:8 a=KKAkSRfTAAAA:8 a=4FHYMocE7i0MHXyxtNQA:9 a=3ZKOabzyN94A:10 a=QEXdDO2ut3YA:10 a=kacYvNCVWA4VmyqE58fU:22 a=cvBusfyB2V15izCimMoJ:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-07-30_07,2026-07-30_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 malwarescore=0 impostorscore=0 priorityscore=1501 bulkscore=0 suspectscore=0 spamscore=0 adultscore=0 clxscore=1015 lowpriorityscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2607300168 From: Dikshita Agarwal Some Iris platforms support both Gen1 and Gen2 HFI firmware images. Update the firmware loading logic to handle this generically by preferring Gen2 when available, while safely falling back to Gen1 when required. The firmware loading logic is updated with the following priority: 1. Device Tree (`firmware-name`): If specified, load unconditionally. 2. Gen2 default : If no DT override exists, select the Gen2 firmware descriptor when present and attempt to load the corresponding firmware image. 3. Gen1 Fallback: If loading the Gen2 firmware fails and a Gen1 descriptor is available, retry with the Gen1 firmware image. Loading and generation detection are split into two steps. iris_load_firmware() applies the priority above and returns the loaded image together with a candidate descriptor. iris_detect_firmware() then runs only after qcom_mdt_load() has succeeded and publishes the chosen descriptor, so the driver commits to a HFI generation only for an image that has actually been loaded. When a platform provides both Gen1 and Gen2 firmware descriptors and the firmware is loaded via a DT override, the candidate descriptor is only a default: iris_detect_firmware() inspects the loaded image to pick the generation, before authentication. It scans the memory populated by qcom_mdt_load() rather than the request_firmware() blob, so that a split .mdt image, whose version string lives in the .bNN data segments and not in the ELF headers, is classified correctly. The firmware is classified as Gen2 if the QC_IMAGE_VERSION_STRING starts with "vfw" or matches the "video-firmware.N.M" format with N >= 2. If a Gen1 firmware image is detected in this case, the driver switches to the Gen1 firmware descriptor and associated platform data so that the correct HFI implementation is used. This change makes firmware generation detection platform‑agnostic, preserves DT overrides, prefers newer Gen2 firmware when available, and maintains compatibility with platforms that only support Gen1. Signed-off-by: Dikshita Agarwal Reviewed-by: Bryan O'Donoghue Co-developed-by: Dmitry Baryshkov Signed-off-by: Dmitry Baryshkov --- drivers/media/platform/qcom/iris/iris_core.c | 2 + drivers/media/platform/qcom/iris/iris_firmware.c | 188 +++++++++++++++++++-- .../platform/qcom/iris/iris_platform_common.h | 6 +- .../media/platform/qcom/iris/iris_platform_vpu2.c | 11 +- .../media/platform/qcom/iris/iris_platform_vpu3x.c | 10 +- drivers/media/platform/qcom/iris/iris_probe.c | 4 - drivers/media/platform/qcom/iris/iris_vidc.c | 1 + 7 files changed, 188 insertions(+), 34 deletions(-) diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c index 8c335dbfce16..676baa8087a8 100644 --- a/drivers/media/platform/qcom/iris/iris_core.c +++ b/drivers/media/platform/qcom/iris/iris_core.c @@ -6,6 +6,7 @@ #include #include "iris_core.h" +#include "iris_ctrls.h" #include "iris_firmware.h" #include "iris_state.h" #include "iris_vpu_common.h" @@ -85,6 +86,7 @@ int iris_core_init(struct iris_core *core) goto error_unload_fw; core->iris_firmware_data->init_hfi_ops(core); + iris_session_init_caps(core); ret = iris_hfi_core_init(core); if (ret) diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c index 1a476146d758..ea3b3a9793e8 100644 --- a/drivers/media/platform/qcom/iris/iris_firmware.c +++ b/drivers/media/platform/qcom/iris/iris_firmware.c @@ -14,22 +14,175 @@ #define IRIS_PAS_ID 9 -#define MAX_FIRMWARE_NAME_SIZE 128 +/* Detect Gen2 firmware by scanning the blob for: + * QC_IMAGE_VERSION_STRING= + * and then checking: + * - version starts with "vfw", OR + * - version matches "video-firmware.N.M" with N >= 2 + */ + +static bool iris_detect_gen2_from_fwdata(const u8 *data, size_t size) +{ + static const char *marker = "QC_IMAGE_VERSION_STRING="; + const size_t mlen = strlen(marker); + static const char *vfw = "vfw"; + const size_t vfwlen = strlen(vfw); + static const char *vf = "video-firmware."; + const size_t vflen = strlen(vf); + + for (size_t i = 0; i + mlen < size; i++) { + const char *found; + + if (memcmp(data + i, marker, mlen)) + continue; + + found = data + i + mlen; + size -= i + mlen; + + /* vfw => Gen2 */ + if (size > vfwlen && !memcmp(found, vfw, vfwlen)) + return true; + + if (size < vflen || + memcmp(found, vf, vflen)) + return false; + + found += vflen; + size -= vflen; + + /* + * video-firmware.1.x is Gen1. + * video-firmware.2.x and video-firmware.10.x are Gen2. + */ + return size >= 2 && + (*found >= '2' || (*found == '1' && found[1] != '.')); + } + + return false; +} -static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name) +/* + * Load the firmware image and return the descriptor that was used to pick the + * file. On a platform that provides only one generation, or when no DT + * firmware-name override is present, the returned descriptor is final. With a + * DT override on a dual-generation platform the returned descriptor is only a + * default; iris_detect_firmware() inspects the loaded image to confirm it. + */ +static const struct firmware *iris_load_firmware(struct iris_core *core, + const char **fw_name, + const struct iris_firmware_desc **fw_desc) { + const struct iris_firmware_desc *desc; + const struct firmware *firmware; + bool has_both_gens; + int ret; + + *fw_name = NULL; + ret = of_property_read_string_index(dev_of_node(core->dev), "firmware-name", 0, fw_name); + + /* + * A platform may support both Gen1 and Gen2 firmware; which one is used + * depends on the firmware image installed on the system, not on the + * hardware. That installed image does not change while the device is + * bound, so the generation is detected only once and the chosen + * descriptor is reused on later core bring-ups (e.g. after a system + * error recovery). + */ + if (core->iris_firmware_desc) { + if (ret) + *fw_name = core->iris_firmware_desc->fwname; + ret = request_firmware(&firmware, *fw_name, core->dev); + if (ret) + return ERR_PTR(ret); + *fw_desc = core->iris_firmware_desc; + return firmware; + } + + has_both_gens = core->iris_platform_data->firmware_desc_gen2 && + core->iris_platform_data->firmware_desc_gen1; + + if (core->iris_platform_data->firmware_desc_gen2) + desc = core->iris_platform_data->firmware_desc_gen2; + else if (core->iris_platform_data->firmware_desc_gen1) + desc = core->iris_platform_data->firmware_desc_gen1; + else + return ERR_PTR(-EINVAL); + + if (ret) { + /* No firmware-name in DT: select by probing Gen2 then Gen1. */ + *fw_name = desc->fwname; + if (has_both_gens) + ret = firmware_request_nowarn(&firmware, *fw_name, core->dev); + else + ret = request_firmware(&firmware, *fw_name, core->dev); + if (ret && has_both_gens) { + desc = core->iris_platform_data->firmware_desc_gen1; + *fw_name = desc->fwname; + ret = request_firmware(&firmware, *fw_name, core->dev); + } + } else { + /* firmware-name given: iris_detect_firmware() picks the gen. */ + ret = request_firmware(&firmware, *fw_name, core->dev); + } + if (ret) + return ERR_PTR(ret); + + *fw_desc = desc; + return firmware; +} + +/* + * Detect the firmware generation and publish the descriptor. Run only after + * qcom_mdt_load() has succeeded, so the driver commits to a HFI generation + * only for a firmware image that has actually been loaded. + * + * The generation is detected from the loaded image (@data / @size point at the + * reserved memory region populated by qcom_mdt_load()) rather than from the + * request_firmware() blob: for a split .mdt the latter holds only the ELF + * headers, while QC_IMAGE_VERSION_STRING lives in the .bNN data segments. + * + * The descriptor and firmware data are published exactly once, before any + * session exists, so the lockless readers in the ioctl paths never observe a + * reassignment. Later bring-ups reuse the already published descriptor. + */ +static void iris_detect_firmware(struct iris_core *core, const char *fw_name, + const u8 *data, size_t size, + const struct iris_firmware_desc *desc) +{ + if (core->iris_firmware_desc) + return; + + /* + * With a DT firmware-name override on a dual-generation platform the + * image on disk decides the generation, so inspect it and switch to the + * Gen1 descriptor when a Gen1 image was loaded. + */ + if (desc == core->iris_platform_data->firmware_desc_gen2 && + core->iris_platform_data->firmware_desc_gen1 && + of_property_present(dev_of_node(core->dev), "firmware-name") && + !iris_detect_gen2_from_fwdata(data, size)) { + dev_info(core->dev, "Gen1 FW detected in %s\n", fw_name); + desc = core->iris_platform_data->firmware_desc_gen1; + } + + /* Publish iris_firmware_data first, then iris_firmware_desc (the guard). */ + core->iris_firmware_data = desc->firmware_data; + core->iris_firmware_desc = desc; +} + +static int iris_load_fw_to_memory(struct iris_core *core) +{ + const struct iris_firmware_desc *desc; const struct firmware *firmware = NULL; struct device *dev = core->dev; struct resource res; phys_addr_t mem_phys; + const char *fw_name; size_t res_size; ssize_t fw_size; void *mem_virt; int ret; - if (strlen(fw_name) >= MAX_FIRMWARE_NAME_SIZE - 4) - return -EINVAL; - ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res); if (ret) return ret; @@ -37,9 +190,9 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name) mem_phys = res.start; res_size = resource_size(&res); - ret = request_firmware(&firmware, fw_name, dev); - if (ret) - return ret; + firmware = iris_load_firmware(core, &fw_name, &desc); + if (IS_ERR(firmware)) + return PTR_ERR(firmware); fw_size = qcom_mdt_get_size(firmware); if (fw_size < 0 || res_size < (size_t)fw_size) { @@ -53,9 +206,14 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name) goto err_release_fw; } + memset(mem_virt, 0, res_size); + ret = qcom_mdt_load(dev, firmware, fw_name, IRIS_PAS_ID, mem_virt, mem_phys, res_size, NULL); + if (!ret) + iris_detect_firmware(core, fw_name, mem_virt, res_size, desc); + memunmap(mem_virt); err_release_fw: release_firmware(firmware); @@ -66,18 +224,12 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name) int iris_fw_load(struct iris_core *core) { const struct tz_cp_config *cp_config; - const char *fwpath = NULL; int i, ret; - ret = of_property_read_string_index(core->dev->of_node, "firmware-name", 0, - &fwpath); - if (ret) - fwpath = core->iris_firmware_desc->fwname; - - ret = iris_load_fw_to_memory(core, fwpath); + ret = iris_load_fw_to_memory(core); if (ret) { - dev_err(core->dev, "firmware download failed\n"); - return -ENOMEM; + dev_err(core->dev, "firmware download failed %d\n", ret); + return ret; } ret = qcom_scm_pas_auth_and_reset(IRIS_PAS_ID); @@ -99,7 +251,7 @@ int iris_fw_load(struct iris_core *core) } } - return ret; + return 0; } int iris_fw_unload(struct iris_core *core) diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h index a9453d539fc2..974809509146 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_common.h +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h @@ -292,11 +292,7 @@ struct iris_firmware_desc { }; struct iris_platform_data { - /* - * XXX: replace with gen1 / gen2 pointers once we have platforms - * supporting both firmware kinds. - */ - const struct iris_firmware_desc *firmware_desc; + const struct iris_firmware_desc *firmware_desc_gen1, *firmware_desc_gen2; const struct vpu_ops *vpu_ops; const struct icc_info *icc_tbl; diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c index fa5bb143158d..bbdbf21961d7 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c @@ -29,6 +29,12 @@ static const struct iris_firmware_desc iris_vpu20_p1_gen1_desc = { .fwname = "qcom/vpu/vpu20_p1.mbn", }; +static const struct iris_firmware_desc iris_vpu20_p1_gen2_s6_desc = { + .firmware_data = &iris_hfi_gen2_data, + .get_vpu_buffer_size = iris_vpu33_buf_size, + .fwname = "qcom/vpu/vpu20_p1_gen2_s6.mbn", +}; + static const struct iris_firmware_desc iris_vpu20_p4_gen1_desc = { .firmware_data = &iris_hfi_gen1_data, .get_vpu_buffer_size = iris_vpu_buf_size, @@ -100,7 +106,8 @@ const struct iris_platform_data milos_data = { }; const struct iris_platform_data sc7280_data = { - .firmware_desc = &iris_vpu20_p1_gen1_desc, + .firmware_desc_gen1 = &iris_vpu20_p1_gen1_desc, + .firmware_desc_gen2 = &iris_vpu20_p1_gen2_s6_desc, .vpu_ops = &iris_vpu2_ops, .icc_tbl = iris_icc_info_vpu2, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu2), @@ -129,7 +136,7 @@ const struct iris_platform_data sc7280_data = { }; const struct iris_platform_data sm8250_data = { - .firmware_desc = &iris_vpu20_p4_gen1_desc, + .firmware_desc_gen1 = &iris_vpu20_p4_gen1_desc, .vpu_ops = &iris_vpu2_ops, .icc_tbl = iris_icc_info_vpu2, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu2), diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c index 2c63adbc5579..74626b35d9cb 100644 --- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c @@ -90,7 +90,7 @@ static const struct tz_cp_config tz_cp_config_vpu3[] = { * - inst_caps to platform_inst_cap_qcs8300 */ const struct iris_platform_data qcs8300_data = { - .firmware_desc = &iris_vpu30_p4_s6_gen2_desc, + .firmware_desc_gen2 = &iris_vpu30_p4_s6_gen2_desc, .vpu_ops = &iris_vpu3_ops, .icc_tbl = iris_icc_info_vpu3x, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), @@ -119,7 +119,7 @@ const struct iris_platform_data qcs8300_data = { }; const struct iris_platform_data sm8550_data = { - .firmware_desc = &iris_vpu30_p4_gen2_desc, + .firmware_desc_gen2 = &iris_vpu30_p4_gen2_desc, .vpu_ops = &iris_vpu3_ops, .icc_tbl = iris_icc_info_vpu3x, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), @@ -154,7 +154,7 @@ const struct iris_platform_data sm8550_data = { * - controller_rst_tbl to sm8650_controller_reset_table */ const struct iris_platform_data sm8650_data = { - .firmware_desc = &iris_vpu33_p4_gen2_desc, + .firmware_desc_gen2 = &iris_vpu33_p4_gen2_desc, .vpu_ops = &iris_vpu33_ops, .icc_tbl = iris_icc_info_vpu3x, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), @@ -185,7 +185,7 @@ const struct iris_platform_data sm8650_data = { }; const struct iris_platform_data sm8750_data = { - .firmware_desc = &iris_vpu35_p4_gen2_desc, + .firmware_desc_gen2 = &iris_vpu35_p4_gen2_desc, .vpu_ops = &iris_vpu35_ops, .icc_tbl = iris_icc_info_vpu3x, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), @@ -220,7 +220,7 @@ const struct iris_platform_data sm8750_data = { * - different num_vpp_pipe */ const struct iris_platform_data x1p42100_data = { - .firmware_desc = &iris_vpu30_p1_gen2_desc, + .firmware_desc_gen2 = &iris_vpu30_p1_gen2_desc, .vpu_ops = &iris_vpu3_ops, .icc_tbl = iris_icc_info_vpu3x, .icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x), diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index 81cccb756b94..5db6398433a4 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -253,8 +253,6 @@ static int iris_probe(struct platform_device *pdev) return core->irq; core->iris_platform_data = of_device_get_match_data(core->dev); - core->iris_firmware_desc = core->iris_platform_data->firmware_desc; - core->iris_firmware_data = core->iris_firmware_desc->firmware_data; core->ubwc_cfg = qcom_ubwc_config_get_data(); if (IS_ERR(core->ubwc_cfg)) @@ -273,8 +271,6 @@ static int iris_probe(struct platform_device *pdev) if (ret) return ret; - iris_session_init_caps(core); - ret = v4l2_device_register(dev, &core->v4l2_dev); if (ret) return ret; diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c index 1c052ca235be..84d70beec350 100644 --- a/drivers/media/platform/qcom/iris/iris_vidc.c +++ b/drivers/media/platform/qcom/iris/iris_vidc.c @@ -9,6 +9,7 @@ #include #include +#include "iris_ctrls.h" #include "iris_vidc.h" #include "iris_instance.h" #include "iris_vdec.h" -- 2.47.3