From patchwork Thu May 16 16:41:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Volodymyr Kharuk X-Patchwork-Id: 797597 Received: from mail-ed1-f45.google.com (mail-ed1-f45.google.com [209.85.208.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2640279FE for ; Thu, 16 May 2024 16:42:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877726; cv=none; b=iGENrfA7XC0Xv8UnIkhiimptmjC089XBCM+9Pik1E3LusogJVF7+g5BjRmsD8kAENCstnrdfbcPEZYULdCxywLEPaRUbnSRAktoAi8qdRzqMUd7tw8Y4TjE8J2ooN/aaVTKCnZ53XOGVaLL/l+R/cAsCz3U9DIofP6hNLxJVGl8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877726; c=relaxed/simple; bh=WTaUGYnA8nbsl8nLAXhtY6rxQ83aC1Nv58FbygyBPdA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=a/V8HOjN4ueBvuMz4rjVGMUvuGpp1pH6pYHAcMYmuG+XUwTWtTMyA+4yQB3hotdCVxQ+ebbBQf452sFHLqYewlmACqDOSL/YFhiUppHOIKCnQgGcJsJB3VS2jfnG71ho03iMJytOBCAZPATd8vwbe560OdmsPzTckfCoOVinxGo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com; spf=pass smtp.mailfrom=melexis.com; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b=KqjrZps+; arc=none smtp.client-ip=209.85.208.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=melexis.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b="KqjrZps+" Received: by mail-ed1-f45.google.com with SMTP id 4fb4d7f45d1cf-572b37afd73so4340154a12.2 for ; Thu, 16 May 2024 09:42:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=melexis.com; s=google; t=1715877723; x=1716482523; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1bEyFm5wcKgbR0Noerq2V2BjAgl0FGLSdsDpoLsS9lA=; b=KqjrZps++g4buIwC490ovsLdaKq1v707Vct718Y7RlJeDquZB315Q8GYPTMSg4ZLKK pAKUiuUvjUxUXQwBPDNoUMaQYWzOCaVMJ45OyLqJzNW37kxwo+dWxVaqHhDEww/gJBiw nZ4QD5L+LZo1VVl46RUrwJ6/nJwIXsylp8wddSTgc/i28egTO+bI4SopU5YiDEjJM7V3 D3XoucUURJU/rErt7IH7extIngMbzsTqwyGAunbrCyg5bHG1zaRBERkPtbFjynT1FM1P cJM1/1GvYjCdukRJmXKbiBNrnUVdkfc80PnFU26CJANsYSlj1Iqhot1wMzlxNVgHPcNG 98hQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715877723; x=1716482523; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=1bEyFm5wcKgbR0Noerq2V2BjAgl0FGLSdsDpoLsS9lA=; b=AK5NDZEByvUA3NgYX0Vz64K5DpPt31pMSnYrXZsOGjyPTiKcuVCG0CUd3IH5u25Yur u2V80Jz0xO3MHtEh0VT56yfUszqQytkK3EI+ou41V3aLJnI6hBob4bS6oSkFzMC0+CkG frW5r7O/8K+twzpbuZJHmUiVtSZg1d14lfx/cSug+DXVeTeuknnngVX2lOo8t7lUOY2B 1kw44bbS5Udtz1bpO8SWsQWRSjXM1aGK7YvkyH88s+GmsfAHU6Aqv3VlGh9AFZidza2e SoV821MQ0q3S8TPnRxFZ7DuRsGb29rSv9CIUVmPIrHh3ZJzBbiH+pJr6KdJRc8xyZUIF Fggw== X-Gm-Message-State: AOJu0YxnEeiqmxH7nQrb1BpffSmwgGT3VcYr033dYgNpUlps22Y910TE 9Nxt/Dd2BwLE6xfMIk3mOFVwN30asdp/7Hpa8aDXUTeoPTvpSDMPPH/idMK8vLKwkVoGUtbSydM hW/zbYWmpxHf3TPbo6D673iSnp3YgRxEMRs0wNysaEb8fyht5wS7O8gI8CubTjAQy0m6hfx5wVc m8N6x9ZsUhTdA42H4mEpFI8qmFph7NG1/gxpkaxkEh X-Google-Smtp-Source: AGHT+IFa1SValMhmtz+0a1u5VMBzR/sAhzAIZDgcR4npkFEeLOcFIKRbnCeumY7rytF2CUfHCXK/Tg== X-Received: by 2002:a50:c002:0:b0:572:7c5d:6ed5 with SMTP id 4fb4d7f45d1cf-5734d5ce3demr13088962a12.22.1715877723572; Thu, 16 May 2024 09:42:03 -0700 (PDT) Received: from melexis ([91.192.181.19]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-574ebdf46cesm3490547a12.37.2024.05.16.09.42.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 May 2024 09:42:03 -0700 (PDT) From: Volodymyr Kharuk To: Cc: Andrii Kyselov , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Laurent Pinchart , devicetree@vger.kernel.org, Hans Verkuil , Sakari Ailus , Benjamin Mugnier , Volodymyr Kharuk Subject: [PATCH v6 01/10] media: uapi: ctrls: Add camera trigger controls Date: Thu, 16 May 2024 19:41:46 +0300 Message-Id: X-Mailer: git-send-email 2.38.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add V4L2_CID_CAMERA_TRIGGER_MODE as a menu item control to set trigger mode. Also proposed some standard modes. Another item is V4L2_CID_CAMERA_TRIGGER as a button to send trigger in V4L2_TRIGGER_MODE_INTERNAL mode. Signed-off-by: Volodymyr Kharuk --- include/uapi/linux/v4l2-controls.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 99c3f5e99da7..7901f40a1bd8 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -1087,6 +1087,14 @@ enum v4l2_auto_focus_range { #define V4L2_CID_HDR_SENSOR_MODE (V4L2_CID_CAMERA_CLASS_BASE+36) +#define V4L2_CID_CAMERA_TRIGGER (V4L2_CID_CAMERA_CLASS_BASE + 37) +#define V4L2_CID_CAMERA_TRIGGER_MODE (V4L2_CID_CAMERA_CLASS_BASE + 38) +enum v4l2_trigger_mode { + V4L2_TRIGGER_MODE_CONTINUOUS = 0, + V4L2_TRIGGER_MODE_INTERNAL = 1, + V4L2_TRIGGER_MODE_EXTERNAL = 2, +}; + /* FM Modulator class control IDs */ #define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900) From patchwork Thu May 16 16:41:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Volodymyr Kharuk X-Patchwork-Id: 797405 Received: from mail-ej1-f41.google.com (mail-ej1-f41.google.com [209.85.218.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 28EB779FE for ; Thu, 16 May 2024 16:42:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877729; cv=none; b=OmlTahjY1mqvcBDMP2DfJuECGioDRFefFo0ed4NDEBJZhY7hjtssafQsl6OcGrgJotUHolfZ0THIG6oKdC0WIREhEHuGwXhQMjubKsmaPOt7pXKDKznGT8o72qcE/QfiWEcL3m9PhuisR7j8TERP3RkkDvk5IaGZEpHfMiVNXFo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877729; c=relaxed/simple; bh=Pi637p/bTB0lkWkPF8F7Ynr0/P72arsieb2+Igg8v48=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=URiriRNSvakXSOYxz9p4GZif2SOUd7lNUsJryamwn2PdgZ6QprSb7OP0QOKZ6iqjVFFFq9p2Qv+rDt1EcLYeRpXe3NgZ8ktnn0rqMyGIg7S0WJDCkQ9OLZ2l1o6N8VzHPcDUNn4PWnH+Hca8cIzMzGuFGAMzhbnwF6CD/uixez8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com; spf=pass smtp.mailfrom=melexis.com; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b=R9GMsiK5; arc=none smtp.client-ip=209.85.218.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=melexis.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b="R9GMsiK5" Received: by mail-ej1-f41.google.com with SMTP id a640c23a62f3a-a5a89787ea4so339240766b.2 for ; Thu, 16 May 2024 09:42:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=melexis.com; s=google; t=1715877726; x=1716482526; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Ej6jwVDe49NxPVP2xZdB0Jv6xzX6u/ARkVFfi+swRno=; b=R9GMsiK5Q0dLK8+BKlm9BCa6UHp0wm7YenAM2Yfhzup6SyE84zJOYr69ZCuDGtP+aJ wDRkSOSSpIdrfeGP+i4jO1wFzxZI3RQyojKqHWC6TorG7pw/XmkIkOommpK4pMylDIJe SzmnVC16NGXMTgbeCVvGzBSrtox0WjpY0+x9vcBcHhtNdxudNZN+n4BnJkZE47WiqPe7 spjHIbL+b7iI6Z9yQg9NBcd55FGj62E2TyEMYwakEazT5cvmFSWnjcWyH+YApljAGTrU PoSjuk+3Tz5lA09ZOAiWMYWAKPYsz2gzlW6LMuOlJn7EHkb0Jpq2cmQnb/4dfyP1oCIX YTRQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715877726; x=1716482526; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Ej6jwVDe49NxPVP2xZdB0Jv6xzX6u/ARkVFfi+swRno=; b=aISsYxO+wGGcuaengXTe1XrctPe0JF0oUQTNKHfHkYNTILWA2ufXF5qZWUisTtbFXJ h9t9z0kCrJSnxG+pyUxcuv59EAe83JjOke+iDe1kmtrScg5K1ziIDsOf8/KjQmFH82ka E0rZ+TBGS1OLrvBsSS/zcIhGh7+Xdihqj4kZW7D67pM/dZ/jaCUfF9W+xpYdljVHxXXb N+Hrmh0Df5u7OTWqXguHdTLZM2HYTGxkzT3rN/nNNqO/3FohT4331RbS9EWRf4Su1ZHR EbHCTg2sGAD5oZ++EoZKEf3GqwIIAGaiXevRcQoVZHrcse+fUeYvLaeX+RXV1WyyegqN pe2A== X-Gm-Message-State: AOJu0YyEpnsgDzX2EppVD931wPauc+lhcARbLEWolQ3v8/LWXFO5bj0q x3FWbsrM4tja9TGZjmwlJRYc/kJlWXm/rwHeqryPJmTj474XgKWeR7xUeRJpzxxvUL6ovNNegzc yhl5saHgbSL5hSf+d7pyOLAUxhMFQ34gagp5uHdGN6LDKZd5DKXZlL10mLXjVs+90GfhOtWv1M0 HqrOATQRPHT5FHHPsyvebM3o/d4HdjHnuICYXR67nT X-Google-Smtp-Source: AGHT+IEEfjI8Kc3o+hOYjuRV9jGg7ljtuNIZI919I5rhvcttKVZf6MMDwbxs3mvjCURVZOJcAkI40A== X-Received: by 2002:a17:907:9455:b0:a59:b88c:2b2a with SMTP id a640c23a62f3a-a5a2d66a7cdmr1557549166b.50.1715877726633; Thu, 16 May 2024 09:42:06 -0700 (PDT) Received: from melexis ([91.192.181.19]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a5a8a55f2e8sm315276666b.126.2024.05.16.09.42.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 May 2024 09:42:06 -0700 (PDT) From: Volodymyr Kharuk To: Cc: Andrii Kyselov , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Laurent Pinchart , devicetree@vger.kernel.org, Hans Verkuil , Sakari Ailus , Benjamin Mugnier , Volodymyr Kharuk Subject: [PATCH v6 02/10] media: v4l: ctrls: Add camera trigger controls Date: Thu, 16 May 2024 19:41:47 +0300 Message-Id: X-Mailer: git-send-email 2.38.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add V4L2_CID_CAMERA_TRIGGER_MODE as a menu item control to set trigger mode. Also proposed some standard modes. Another item is V4L2_CID_CAMERA_TRIGGER as a button to send trigger in V4L2_TRIGGER_MODE_INTERNAL mode. Signed-off-by: Volodymyr Kharuk --- drivers/media/v4l2-core/v4l2-ctrls-defs.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c index 8696eb1cdd61..db596cb43ad0 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c @@ -611,6 +611,12 @@ const char * const *v4l2_ctrl_get_menu(u32 id) "Cyclic", NULL, }; + static const char * const camera_trigger_mode[] = { + "Continuous", + "Internal", + "External", + NULL, + }; switch (id) { case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: @@ -750,6 +756,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id) return camera_orientation; case V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE: return intra_refresh_period_type; + case V4L2_CID_CAMERA_TRIGGER_MODE: + return camera_trigger_mode; default: return NULL; } @@ -1086,6 +1094,8 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_CAMERA_ORIENTATION: return "Camera Orientation"; case V4L2_CID_CAMERA_SENSOR_ROTATION: return "Camera Sensor Rotation"; case V4L2_CID_HDR_SENSOR_MODE: return "HDR Sensor Mode"; + case V4L2_CID_CAMERA_TRIGGER: return "Camera Trigger"; + case V4L2_CID_CAMERA_TRIGGER_MODE: return "Camera Trigger Mode"; /* FM Radio Modulator controls */ /* Keep the order of the 'case's the same as in v4l2-controls.h! */ @@ -1342,6 +1352,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_AUTO_FOCUS_START: case V4L2_CID_AUTO_FOCUS_STOP: case V4L2_CID_DO_WHITE_BALANCE: + case V4L2_CID_CAMERA_TRIGGER: *type = V4L2_CTRL_TYPE_BUTTON; *flags |= V4L2_CTRL_FLAG_WRITE_ONLY | V4L2_CTRL_FLAG_EXECUTE_ON_WRITE; @@ -1420,6 +1431,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_CAMERA_ORIENTATION: case V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE: case V4L2_CID_HDR_SENSOR_MODE: + case V4L2_CID_CAMERA_TRIGGER_MODE: *type = V4L2_CTRL_TYPE_MENU; break; case V4L2_CID_LINK_FREQ: From patchwork Thu May 16 16:41:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Volodymyr Kharuk X-Patchwork-Id: 797596 Received: from mail-ed1-f51.google.com (mail-ed1-f51.google.com [209.85.208.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6EC024C94 for ; Thu, 16 May 2024 16:42:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877733; cv=none; b=bvbfmY81vU6QmuiThpj+1dFpuPr2K6plXwMt0BZ0SytbjusdOUSd5KB6vsJzcP4OcG5p4gLRN/Ga27sGYFaUSrssrviLab11IlIZiETmH3r1C1zqdqX+s5oG/Ou7RcLQEHt0KQjuP4zAMktM7hs6yqlW2x7oxeJxGpJkwOiLvs0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877733; c=relaxed/simple; bh=Z2Up8NdNWpwOPvHkVPSkQzmGpXgQHnv35kuhg72/dno=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=f1/01oJlI9+XyXQkDUy5OotvivIArXFxPi0J4uaF2+mjG0dr/R6i7CBIi5/PXE9Z3lqawK1JWyFMnfddXjwRrfN9gqGmJJC8dxKcCsIhTmCV6TRz9zc+c8AQH5nApEP211jLTc5wqN4WR4oappVxT+KSl95neiqpA5ObdC2m94o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com; spf=pass smtp.mailfrom=melexis.com; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b=oAHc1LLS; arc=none smtp.client-ip=209.85.208.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=melexis.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b="oAHc1LLS" Received: by mail-ed1-f51.google.com with SMTP id 4fb4d7f45d1cf-5723edf0ae5so3511559a12.0 for ; Thu, 16 May 2024 09:42:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=melexis.com; s=google; t=1715877730; x=1716482530; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Kd2BP40fUxe3iXqLrCdtO0arn/PW8G+mlzZObTv2eB8=; b=oAHc1LLSmoXSGD5Ws95cutBHMTTVgPgKGmoXobH1ifSi9TyDBruyoFMvsZ+rGDb3DW K3OJ2w6xWylpYEgjC9CsQPNWBIeqyhEyIyHzWPbbidKKEsU0WRHOtOJGLys1Zy0S5KBV qNkno5UX4T9XG5hIeRMe2m3cx4v5hBsfa/sKsobd7RnS+DroX4IjAbB/AqIyb/LSmZ3h pzMupe4hZk6ad9l2KYHmlogp8c4fhkBsmGZS3+aTGeNXKy68NSaWrTkiBAt6MwkPj51v KGswV+REzG48fs0YzaBXNqOB/zTQYcBx4xrKh1+UwMh8RblbsmUGtxq8ko6wJq0Zyotv fL0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715877730; x=1716482530; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Kd2BP40fUxe3iXqLrCdtO0arn/PW8G+mlzZObTv2eB8=; b=vOkZBhpCKnjrnoNFhexf2KrBCzgZALF1RE/TiKl1FL4E8X6z/QdEZCxWH4vTGMXnm0 Z/kW/sMXJyANd77KFTy6vih98JUZ2QEbo0alvfztACUWWQOdxL8UZFTHIf8SNCfRt2gf 3A/HPiWkVics/NwJirimQXOXtamdJbT05iMjASLpJVXGRYfeqS7uFhPJ4yNPAar0sYlM 3jhKDly+WfnF2QaZYwwfom7fZCFj2G8qOIYnL6Yg9Rdm+JAdHVRzM/+6dAFZ2n4mlAfl r3nnyN0GI8OE+n9Nz+vmLGQdkYOm0nibSEeEH/9uSsgdOq/3+1PY2lwxeTw9OwPYsky+ vPsA== X-Gm-Message-State: AOJu0Yy80p33nwWrDWBzhFvYup8LnI+OOlPR0b+ABN16pvoGhsZaLhZu w6cVCmw4OW8s6H+ej4OXykaqfLMf5sxDL3PijuOAZSdTA3Uoatb0y91Ph6QNmNY2CHb8Iuz4auB i6PRhPQyMSgbUsa0z6zwZIo1l53WQc5m8pVidy9uCNATpidXKE1UJf5xcFkurE57T5nwidSHJtZ fLUF5qyPdDs9iokJEGtadxUWJ6sK5QKplNN3e9r9GF X-Google-Smtp-Source: AGHT+IFoBv4qFB8tusulro970FDf32Yd7hCImB/40oyR/6oHGniRsD3ojCeaDfGVwFWuKqLReE2xIg== X-Received: by 2002:a50:d791:0:b0:572:707f:1a99 with SMTP id 4fb4d7f45d1cf-5734d5d3747mr12697360a12.25.1715877729821; Thu, 16 May 2024 09:42:09 -0700 (PDT) Received: from melexis ([91.192.181.19]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5733becfb83sm10694063a12.46.2024.05.16.09.42.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 May 2024 09:42:09 -0700 (PDT) From: Volodymyr Kharuk To: Cc: Andrii Kyselov , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Laurent Pinchart , devicetree@vger.kernel.org, Hans Verkuil , Sakari Ailus , Benjamin Mugnier , Volodymyr Kharuk Subject: [PATCH v6 03/10] media: uapi: ctrls: Add Time of Flight class controls Date: Thu, 16 May 2024 19:41:48 +0300 Message-Id: X-Mailer: git-send-email 2.38.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Define Time of Flight class controls. Also add most common TOF controls: - phase sequence - time integration - frequency modulation Signed-off-by: Volodymyr Kharuk Acked-by: Benjamin Mugnier --- include/uapi/linux/v4l2-controls.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 7901f40a1bd8..3ac204818bdf 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -30,6 +30,7 @@ #define V4L2_CTRL_CLASS_DETECT 0x00a30000 /* Detection controls */ #define V4L2_CTRL_CLASS_CODEC_STATELESS 0x00a40000 /* Stateless codecs controls */ #define V4L2_CTRL_CLASS_COLORIMETRY 0x00a50000 /* Colorimetry controls */ +#define V4L2_CTRL_CLASS_TOF 0x00a60000 /* Time of flight camera controls */ /* User-class control IDs */ @@ -3499,6 +3500,13 @@ struct v4l2_ctrl_av1_film_grain { __u8 reserved[4]; }; +#define V4L2_CID_TOF_CLASS_BASE (V4L2_CTRL_CLASS_TOF | 0x900) +#define V4L2_CID_TOF_CLASS (V4L2_CTRL_CLASS_TOF | 1) + +#define V4L2_CID_TOF_PHASE_SEQ (V4L2_CID_TOF_CLASS_BASE + 0) +#define V4L2_CID_TOF_FREQ_MOD (V4L2_CID_TOF_CLASS_BASE + 1) +#define V4L2_CID_TOF_TIME_INTEGRATION (V4L2_CID_TOF_CLASS_BASE + 2) + /* MPEG-compression definitions kept for backwards compatibility */ #ifndef __KERNEL__ #define V4L2_CTRL_CLASS_MPEG V4L2_CTRL_CLASS_CODEC From patchwork Thu May 16 16:41:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Volodymyr Kharuk X-Patchwork-Id: 797404 Received: from mail-ej1-f42.google.com (mail-ej1-f42.google.com [209.85.218.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 573DD63BF for ; Thu, 16 May 2024 16:42:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877736; cv=none; b=dTTeAMDNgWlgY2wKNtPglxx0rM72R0Qj7Ys+m0eeYCbop4rk9qUMv/6ITJonuGAoOvihSrHCyr9PTjdaSaOA82KWVx+KsrUEP3mgzR2JPQfANQs4jtNgs2Fg9dAl0XFIWlBHozaP2WmVMwBz3jigeCKzztTXEnA3CK5YFZViEwI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877736; c=relaxed/simple; bh=alJQ6riM1LX9FIYE0B2o3uu7wFCy8RXzmTCI8lK6Om4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=gkMamv4hXMyHGk9N3yhTCVoZfZu3Nd+TQIx7LRZzzagtiMwCC7gdyklgbZ4nomJ7ZPNPn3RDTER6TUC+AKIBDISBoYGHujw2stpR5BDt8WcnO3VCSrOZ4jon7WYUptO/9UHG6vtQSwzi2uDocyvn/1zeHzDjqU9HKNTdXFj9aj0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com; spf=pass smtp.mailfrom=melexis.com; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b=QYOnM0cy; arc=none smtp.client-ip=209.85.218.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=melexis.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b="QYOnM0cy" Received: by mail-ej1-f42.google.com with SMTP id a640c23a62f3a-a59c5c9c6aeso346354666b.2 for ; Thu, 16 May 2024 09:42:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=melexis.com; s=google; t=1715877733; x=1716482533; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JJbbquUuFYlyR0DXePZ8R2GDsWo7iL9ZJhKoHm9Pgs8=; b=QYOnM0cyiyTN2sysu8cgM1fx8e3m3xfG1aFoDIHbc/l/U4k0Z2FZ145oTlY1qx+Mtg LYok9xzyr0G7kytWdfORE1m8T+tcy5COrJ5ePJEUPXW0lu/9IAWIY8bqyCdyojeEtGy/ 6Ayld47Xh4oT37i4HaxBLfS5yaYFV6U6qR7Gudk/7ffvoZ2YmMygeU47LwinHmNcCD0e EcCm5J8NFeWgI3tMMNshmWY3kJqVJcPlUXE2h+OGG6pTK3XEuWcc7EwCSygLwnUREbrX 9N8B31o8mk3umB7upEcGAk3yZxss3TwCnevvBWEZC3lo5zDbsO2ZbqQrcU+mqOIG2wXO YUzg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715877733; x=1716482533; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JJbbquUuFYlyR0DXePZ8R2GDsWo7iL9ZJhKoHm9Pgs8=; b=D6KKrspaokOZSqLMpBCGNx44F43Vmyx7bZ8jwSUWA/W1cRZuRaGxAcryBlw2Jqv4MZ mwOC3m7ntDIYf7Ccy/XDi6mZWtfjj3t8taVOrhBwcbxupgMEvGWS+VLo4CQyIEkxOCaH DbkMaBgcMl4L8tHPmzz4IHtPxxPz3CnnRAH+ShXSK7AcTQm1g3KF3YaHQK9OtadXCG2Z uKT+jCjeNLz+XmVtfjlahwiiUWXwQMKFVuMWNVvslSEeIwPktFDrHBtBLImxfHEt5bQa FhIbCQFt+XCyQoVGx+TwmZnMRw+iar4HIwa38PgTmR/iDr6sXl89at2OY5rk+HOynubE LSbg== X-Gm-Message-State: AOJu0Yy8s8V1Pe89rWmxLiCNJqJI45BITJxm16OFlD/QykBPRYcwoH3P TEm8n6njfJlxiwwflbdI7KZCdaS1yHiHJ3YJVfi98Uvfg3WSUXPPCYPt3JKC5ycdxRfNQb28suM AbgL2bcTn8NiUdslrE9IoCOibvuteviSCYbPW1evK5yh7RmyF5c5/vFOrYtkF2OUthrl87WyeMV /K3qRxTOyJywqIHczX8lVu2qD4ehdUi9Wg3WM0Oglm X-Google-Smtp-Source: AGHT+IEoTmPYnnZUtQvyZDjO3o9XekoX/3nMH2nUsz5wDT97DiFeyV0y1NTyXq1UjUAZ37yTIg1z+Q== X-Received: by 2002:a17:906:da8d:b0:a58:ea85:9114 with SMTP id a640c23a62f3a-a5a2d672fb6mr1600297266b.50.1715877732754; Thu, 16 May 2024 09:42:12 -0700 (PDT) Received: from melexis ([91.192.181.19]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a5a178a9f0fsm995174566b.69.2024.05.16.09.42.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 May 2024 09:42:12 -0700 (PDT) From: Volodymyr Kharuk To: Cc: Andrii Kyselov , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Laurent Pinchart , devicetree@vger.kernel.org, Hans Verkuil , Sakari Ailus , Benjamin Mugnier , Volodymyr Kharuk Subject: [PATCH v6 04/10] media: v4l: ctrls: Fill V4L2_CID_TOF_CLASS controls Date: Thu, 16 May 2024 19:41:49 +0300 Message-Id: <69e2cb692e63f9cf1f347fcc10de5c634c8643bc.1715871189.git.vkh@melexis.com> X-Mailer: git-send-email 2.38.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Define names, flags and types of TOF controls. *dims* is driver specific. It also means, that it is not possible to use new_std for arrays. Signed-off-by: Volodymyr Kharuk Acked-by: Benjamin Mugnier --- drivers/media/v4l2-core/v4l2-ctrls-defs.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c index db596cb43ad0..18085b800c32 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c @@ -1252,6 +1252,13 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_COLORIMETRY_CLASS: return "Colorimetry Controls"; case V4L2_CID_COLORIMETRY_HDR10_CLL_INFO: return "HDR10 Content Light Info"; case V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY: return "HDR10 Mastering Display"; + + /* Time of light camera controls */ + /* Keep the order of the 'case's the same as in v4l2-controls.h! */ + case V4L2_CID_TOF_CLASS: return "Time of Flight Camera Controls"; + case V4L2_CID_TOF_PHASE_SEQ: return "TOF Phase Sequence"; + case V4L2_CID_TOF_FREQ_MOD: return "TOF Frequency Modulation"; + case V4L2_CID_TOF_TIME_INTEGRATION: return "TOF Time Integration"; default: return NULL; } @@ -1463,6 +1470,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_DETECT_CLASS: case V4L2_CID_CODEC_STATELESS_CLASS: case V4L2_CID_COLORIMETRY_CLASS: + case V4L2_CID_TOF_CLASS: *type = V4L2_CTRL_TYPE_CTRL_CLASS; /* You can neither read nor write these */ *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY; @@ -1614,6 +1622,18 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY: *type = V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY; break; + case V4L2_CID_TOF_PHASE_SEQ: + *type = V4L2_CTRL_TYPE_U16; + *flags |= V4L2_CTRL_FLAG_DYNAMIC_ARRAY; + break; + case V4L2_CID_TOF_FREQ_MOD: + *type = V4L2_CTRL_TYPE_U32; + *flags |= V4L2_CTRL_FLAG_DYNAMIC_ARRAY; + break; + case V4L2_CID_TOF_TIME_INTEGRATION: + *type = V4L2_CTRL_TYPE_U16; + *flags |= V4L2_CTRL_FLAG_DYNAMIC_ARRAY; + break; default: *type = V4L2_CTRL_TYPE_INTEGER; break; From patchwork Thu May 16 16:41:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Volodymyr Kharuk X-Patchwork-Id: 797595 Received: from mail-ed1-f44.google.com (mail-ed1-f44.google.com [209.85.208.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D04DC1DFE4 for ; Thu, 16 May 2024 16:42:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877740; cv=none; b=HEL0L5MJMR1Qqeohh2SeGM4oGdItzxKnhZ0UJBtms8z3oHmheWIM5UMVg08jXSOnaOn5lw1Ao0o/Bo2Otut648VDvA53f5y+WNtRBPs4+uFkd+fHtdmE9vQCvc9y+/Q2ESN2H1glXLV1cCLM/d/FibhmWYQUsjdKf60OjzCrBPA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877740; c=relaxed/simple; bh=j04eimfjyUgU2H082lOSUcXZZ9IlONK3OkpU84cro0M=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=r7gMkwkc+YXSbkSeUgNotU2D1ZWX0CzF8kWAliqGD8LKu3d1AUehXZQ+04KZiyz4SxgZ+gV8q7jR5B1Gs3nbMDW65rW4DYjkElzaoV0co8fNAJ3xaOpf0lZ3cSFqjk05nWyqpdkrlECfn+Hvy806Z7ZZpjfg6adHdz68uKjZyx4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com; spf=pass smtp.mailfrom=melexis.com; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b=WVMJ3I+/; arc=none smtp.client-ip=209.85.208.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=melexis.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b="WVMJ3I+/" Received: by mail-ed1-f44.google.com with SMTP id 4fb4d7f45d1cf-571ba432477so4098714a12.1 for ; Thu, 16 May 2024 09:42:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=melexis.com; s=google; t=1715877736; x=1716482536; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=BXTYAMw4Ajg6uSzD9GLExqk/KcGPmBaTriWW0Oj6lRg=; b=WVMJ3I+/13wztsWUl/QUjePs5vIwtiVI84O3VibCdQ2kb31RUriCT4XLOji3Otqj2Z 5/zeGIgEze7pQjDqaahaY4OFon+WxreD+S8bpuhBVSmcnFEeZQ2YEI0T0xIMdKQcF8iu SutK9Q9tuM1GF1Mvm72wBp5fdNBjTOb/l1pybZyubhHcWEFPidXYXG4L13Msc93kgd6x PMzagJ7djEtcdN1m1xacJ7s8m5Jw3I9ng2YyrqEsm9Usu1awIJq528wvHlZZZiha4yja toSaIsHBMcMTtQLN8nlW0mVw3j/WNGE4GUVHMwL2vJw9MS/0MaOm7V6RHgTg25otkIvW Y7fw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715877736; x=1716482536; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=BXTYAMw4Ajg6uSzD9GLExqk/KcGPmBaTriWW0Oj6lRg=; b=j0P6Pje2ocZYxPS444VKCFKzqotHYsgNvZ3EgnqJWPM/Ys9voGORBH+BCKw4eJW7zb PzCII0bbqm+Wwql4wmEUpiPcbn+exE5PPuM5cKCW+Y9hT9o2tT1YvSj2hQhFSt527Txi qJyK0aM4tYPVCTCIsCrqdqLhxuiv9Ai9bguo0rAIz1hFsnHzurfYdhWuKaG0QMIC5Xml Xcx9e5E1yWvu3NzBVuR2/4QzNrx8xDWkRG9hOIIzeGNSCLMPxBJS8aMEqwajDABrROve sXGXne/5WAA1ljjldfbZw3Xlhv3SUE3G7/40++AeCKPqrefZBzbDImnNexweC/YTctdV UwJw== X-Gm-Message-State: AOJu0Ywns+5InxeKex00WLOmfxQ7KaoWRYB4OFxYlHmSALWsA7xmp4sA 2S/D9JkzoGL82x4fCOvRnS6OlLJArz2Wa9LRguCNfU2T1OG0DM7GYxnxe3qqJM7aJbp9UDgQ9It AIqa83ga21F27411B3dMhW/HnHhrKHSpTIfz7v3dOtBFEcsOCwV9aADvQQE5kFeSIstbfueuJOQ PoRPleNRw6+I9x7/JetmI4+nVM3cCF8brFJtj0Gk+d X-Google-Smtp-Source: AGHT+IHnGdB75nuvKaKJ3eLN8yhVPH5jsKWtZ2nuM+gj65Hc9dZ3akCfwRxJwyB56JtMGr4Qa6gEMw== X-Received: by 2002:a17:906:40c:b0:a59:dd90:baeb with SMTP id a640c23a62f3a-a5a2d641583mr1389923666b.48.1715877736241; Thu, 16 May 2024 09:42:16 -0700 (PDT) Received: from melexis ([91.192.181.19]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a5a1781cf60sm1011443666b.14.2024.05.16.09.42.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 May 2024 09:42:16 -0700 (PDT) From: Volodymyr Kharuk To: Cc: Andrii Kyselov , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Laurent Pinchart , devicetree@vger.kernel.org, Hans Verkuil , Sakari Ailus , Benjamin Mugnier , Volodymyr Kharuk Subject: [PATCH v6 05/10] media: Documentation: v4l: Add TOF class controls Date: Thu, 16 May 2024 19:41:50 +0300 Message-Id: <6b0e58f60cbfe55a2c0fc14135d6453b53721f19.1715871189.git.vkh@melexis.com> X-Mailer: git-send-email 2.38.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add description about V4L2_CID_TOF_PHASE_SEQ, V4L2_CID_TOF_FMOD and V4L2_CID_TOF_TINT. Also updated MAINTAINERS with new ext-ctrls-tof file. Signed-off-by: Volodymyr Kharuk Acked-by: Benjamin Mugnier --- .../userspace-api/media/v4l/common.rst | 1 + .../userspace-api/media/v4l/ext-ctrls-tof.rst | 56 +++++++++++++++++++ MAINTAINERS | 7 +++ 3 files changed, 64 insertions(+) create mode 100644 Documentation/userspace-api/media/v4l/ext-ctrls-tof.rst diff --git a/Documentation/userspace-api/media/v4l/common.rst b/Documentation/userspace-api/media/v4l/common.rst index ea0435182e44..1ea79e453066 100644 --- a/Documentation/userspace-api/media/v4l/common.rst +++ b/Documentation/userspace-api/media/v4l/common.rst @@ -52,6 +52,7 @@ applicable to all devices. ext-ctrls-fm-rx ext-ctrls-detect ext-ctrls-colorimetry + ext-ctrls-tof fourcc format planar-apis diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-tof.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-tof.rst new file mode 100644 index 000000000000..fd8969d3d354 --- /dev/null +++ b/Documentation/userspace-api/media/v4l/ext-ctrls-tof.rst @@ -0,0 +1,56 @@ +.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later + +.. _tof-controls: + +*************************************** +Time of Flight Camera Control Reference +*************************************** + +The Time of Flight class includes controls for digital features +of the TOF sensor. + +TOF sensor is a receiver chip. Each pixel in the sensor measures the travel time +of light to that pixel and hence the distance to the object seen by that pixel. +There are different types of TOF sensors. Direct TOF sensors (also known +as Lidars) send a single pulse and measure direct time of flight. +Another type of TOF is indirect TOF sensors, which emit continuous wave +(could be radio or infrared) and then measure phase shift of reflected light. +The sensor modulates outgoing light and then collects reflected photons +as an electric charge with modulated pattern. Knowing the frequency of +the pattern you can calculate the real distance. + +For more information about TOF sensors see +`TOF `__ from Wikipedia. +Also, there are other nice explanations from vendors about indirect TOF: +`Microsoft `__, +`Melexis `__, +`TI `__. + +.. _tof-control-id: + +Time of Flight Camera Control IDs +================================= + +``V4L2_CID_TOF_CLASS (class)`` + The TOF class descriptor. Calling :ref:`VIDIOC_QUERYCTRL` for + this control will return a description of this control class. + +``V4L2_CID_TOF_PHASE_SEQ (dynamic array u16)`` + Change the shift between illumination and sampling for each phase + in degrees. The distance / amplitude (confidence) pictures are obtained + by merging 3..8 captures of the same scene using different phase shifts + (some TOF sensors use different frequency modulations). + + The size of dynamic array specify the number of captures. + Also driver may decide whether V4L2_CID_TOF_FREQ_MOD and + V4L2_CID_TOF_TIME_INTEGRATION should change the number + of captures or rely on V4L2_CID_TOF_PHASE_SEQ control. + The maximum size of the array is driver specific. + +``V4L2_CID_TOF_FREQ_MOD (dynamic array u32)`` + The control sets the modulation frequency (in Hz) for each phase. + The maximum array size is driver specific. + +``V4L2_CID_TOF_TIME_INTEGRATION (dynamic array u16)`` + The control sets the integration time (in us) for each phase. + The maximum array size is driver specific. diff --git a/MAINTAINERS b/MAINTAINERS index ef6be9d95143..de46c28bb3f2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14012,6 +14012,13 @@ S: Supported W: http://www.melexis.com F: drivers/iio/temperature/mlx90635.c +MELEXIS MLX7502X DRIVER +M: Volodymyr Kharuk +L: linux-media@vger.kernel.org +S: Supported +W: http://www.melexis.com +F: Documentation/userspace-api/media/v4l/ext-ctrls-tof.rst + MELFAS MIP4 TOUCHSCREEN DRIVER M: Sangwon Jee S: Supported From patchwork Thu May 16 16:41:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Volodymyr Kharuk X-Patchwork-Id: 797403 Received: from mail-ej1-f53.google.com (mail-ej1-f53.google.com [209.85.218.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9FDF879DF for ; Thu, 16 May 2024 16:42:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877742; cv=none; b=XXbHxT77eFiXF4VfP8X5BQVVWD7APe5F17+6sztax6Oesz0QarCTA9Ygeg3ePsOmc0MjwlDkSodsKxwSitlGjlbbfyW8ql0kJzmy5Y7iImgF4AanexF9GB29s3zsq1f9pX6V23uAIhpoXlpeqz6nGtmwNVX8udqD7oT/FcyxoVA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877742; c=relaxed/simple; bh=jGqzhaOd16cpVcsnK4AsE1lanw1GigLr24tQMLYItF0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ZsHD5XpKn/UoUqO3Gj7vdHlAzlmq4XlH5Qg00mio8OOZTtsv8JgeKJ7VApVLqAU/tVYb25S3L2WRAiMgdqu0GSzGCE26GyCaLvMTsuuIxc3IC4PEMeH2/7rvZtDaOiYUZiJJ4B+LWPPubPNl1+Q90P7VuwwsguO9CeFVv+JfDSg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com; spf=pass smtp.mailfrom=melexis.com; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b=l+zMY4tk; arc=none smtp.client-ip=209.85.218.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=melexis.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b="l+zMY4tk" Received: by mail-ej1-f53.google.com with SMTP id a640c23a62f3a-a59ab4f60a6so275051266b.0 for ; Thu, 16 May 2024 09:42:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=melexis.com; s=google; t=1715877739; x=1716482539; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=x86b2pC0BGkgc9pZoaWR80EZrkXbOTilbfMfMb6B3+0=; b=l+zMY4tkmNN5KtTmuSr8WOU1UOtakVjcklz6+t6vTCUw4WAnXhIZFivVRSoEeTWzoH XJroM9cgdafAJkkdM0Oosk9zrV+GY9Kx5uoBL0ds/uzaCWuO2FUEhvff7PccWGZt1+42 GePwwn6H1ezBNFaz2RwD0DdPejCvf0YGiINeWs1lQHzHSnypZmldPxZLLDOnJLR2bH2c adp0HmkBp/rgYkuPsokNLJdW6STZqd8kyg+iZKNcdFq3cZEKBH4zKzlKA72S8I4/PagN +hVlzvzfAUbqMFGQr0bSX6JUtREW2yVnfr+HXyBnIF1d2aJ08XH797/ytEm6PtLbfZm0 k3wg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715877739; x=1716482539; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=x86b2pC0BGkgc9pZoaWR80EZrkXbOTilbfMfMb6B3+0=; b=QpaWR5KK9WIOME9dUeeqOnEaqSbNgfiaHzFxaxAQXZP7lm08XYxSpOV+A71Sa/fHUC LjBuDFYvunpVvqCDuH67ilcXKmXINrK2JwCoVTGuQN09xgb4UfOzVCri+Ti9hFUOQUZG h+Cze/DpzVm6rBSEjjuoigI+VA23zFJbphDyI8WdHJdd/T505Da29DmqEJWg0+fFVuic Jvt1u1gKApl01nYWHgyAQErMPGIAMzD8BG1rD4ljviQJdEr+Wy/eB+2tLsS7ZJ+r8eqV FN/1XBehfSKxZm3z9QZ/3QQJBkaf5KiHxd8+LFulMVsaMD8l4vEWOzobRTxEgqZRC5q0 3RAA== X-Gm-Message-State: AOJu0YxjYuWTthFDgBcpBCV4of4v0bIVYLmbox/LEPAyAXg+O3bAUFjw qnF+g7bYhqB6Ri73wiZ4K2ifXyg2FKjMJa3H5/OgnSL/qcqAlh0MfDsV5UBXNIXAlfPaY2qmJxG MZ0+S3/laa4GdoUqpw/tZRC5cSH94MTDy7p5UD8XjpAWwDKz5HeW+I7uhNRF4EA/DcsYd6GIcRI dDxLg1+90VrNo6htbIhzR7oW2X+QJCMixadmHp1w/5 X-Google-Smtp-Source: AGHT+IHMA/7KS4nXZp1n19NAbIpGBUaNCGnqr2Ma53AhWlNvJ1WlcykMbVpaHMIG+C8VAROpqCcqWQ== X-Received: by 2002:a17:906:c452:b0:a59:9da0:cc1 with SMTP id a640c23a62f3a-a5a2d65fcf7mr2046631566b.58.1715877739202; Thu, 16 May 2024 09:42:19 -0700 (PDT) Received: from melexis ([91.192.181.19]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a5a179c7e9bsm996991266b.134.2024.05.16.09.42.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 May 2024 09:42:19 -0700 (PDT) From: Volodymyr Kharuk To: Cc: Andrii Kyselov , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Laurent Pinchart , devicetree@vger.kernel.org, Hans Verkuil , Sakari Ailus , Benjamin Mugnier , Volodymyr Kharuk Subject: [PATCH v6 06/10] media: v4l: ctrls-api: Allow array update in __v4l2_ctrl_modify_range Date: Thu, 16 May 2024 19:41:51 +0300 Message-Id: <7789f15cfbad2c145e5b4b99b790be2da01fbf32.1715871189.git.vkh@melexis.com> X-Mailer: git-send-email 2.38.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 For V4L2_CID_TOF_TINT, which is dynamic array, it is required to use __v4l2_ctrl_modify_range. So the idea is to use type_ops instead of u64 from union. It will allow to work with any type. Signed-off-by: Volodymyr Kharuk --- drivers/media/v4l2-core/v4l2-ctrls-api.c | 25 ++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls-api.c b/drivers/media/v4l2-core/v4l2-ctrls-api.c index e5a364efd5e6..f65d6114592c 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-api.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-api.c @@ -934,17 +934,18 @@ int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl, lockdep_assert_held(ctrl->handler->lock); switch (ctrl->type) { + case V4L2_CTRL_TYPE_MENU: + case V4L2_CTRL_TYPE_INTEGER_MENU: + if (ctrl->is_array) + return -EINVAL; + fallthrough; case V4L2_CTRL_TYPE_INTEGER: case V4L2_CTRL_TYPE_INTEGER64: case V4L2_CTRL_TYPE_BOOLEAN: - case V4L2_CTRL_TYPE_MENU: - case V4L2_CTRL_TYPE_INTEGER_MENU: case V4L2_CTRL_TYPE_BITMASK: case V4L2_CTRL_TYPE_U8: case V4L2_CTRL_TYPE_U16: case V4L2_CTRL_TYPE_U32: - if (ctrl->is_array) - return -EINVAL; ret = check_range(ctrl->type, min, max, step, def); if (ret) return ret; @@ -962,16 +963,16 @@ int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl, } cur_to_new(ctrl); if (validate_new(ctrl, ctrl->p_new)) { - if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64) - *ctrl->p_new.p_s64 = def; - else - *ctrl->p_new.p_s32 = def; + WARN_ON(ctrl->is_array); /* This shouldn't happen, as + * INTEGER/Ux/BOOLEAN/BITMASK will not + * return an error. + * In case it happened, all array will + * set to default value + */ + ctrl->type_ops->init(ctrl, 0, ctrl->p_new); } - if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64) - value_changed = *ctrl->p_new.p_s64 != *ctrl->p_cur.p_s64; - else - value_changed = *ctrl->p_new.p_s32 != *ctrl->p_cur.p_s32; + value_changed = !ctrl->type_ops->equal(ctrl, ctrl->p_cur, ctrl->p_new); if (value_changed) ret = set_ctrl(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE); else if (range_changed) From patchwork Thu May 16 16:41:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Volodymyr Kharuk X-Patchwork-Id: 797594 Received: from mail-ej1-f42.google.com (mail-ej1-f42.google.com [209.85.218.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CA3D58BFA for ; Thu, 16 May 2024 16:42:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877745; cv=none; b=ODy8LLbPyf8jSNF82aHkguNVoEbs2IzJDw3da3f0jma7J+cMsUudy0wDSmqhU2CTzE4iNHBqCGj/QjuyqIHRTe1VnZkPqhmC9IwZzxiQ0+I5H4/EyGQ9w2xPSZfRHd4phoNAlHq5eT70Q1VCMNtaI8jM/WwoZYq4BlQ/dhQ7OBE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877745; c=relaxed/simple; bh=UwgZknUu6CAOz/IR9be36P6hpO03NDzOxnGjt8+Y30I=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=glIlzGPHtrDrig0J7CJIx4w/IX6jJMhceqzVGKxYkgVxJ2ahxXvaFN0eD5k3Ceng7feHOHuJbGPkeTQ569+dk9m+J0vXSdJXNsSl2McrgCdfsJKF+wUNkFWVytfFfbV17k5ua/Q2HqoiQnljg9hpY1rbaLkOXrttsGRH85GXZug= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com; spf=pass smtp.mailfrom=melexis.com; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b=LnDRW9sO; arc=none smtp.client-ip=209.85.218.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=melexis.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b="LnDRW9sO" Received: by mail-ej1-f42.google.com with SMTP id a640c23a62f3a-a5a88339780so364770666b.0 for ; Thu, 16 May 2024 09:42:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=melexis.com; s=google; t=1715877742; x=1716482542; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8dfDoFjby3SyG/aRSMt4bJnHeuy60vGajFgy+PGk0RM=; b=LnDRW9sOcAzbgiinfza8PjVTnmLmCzl+CbVJ8rP1KXbIL7jn/FpurtjlBEvzn5JWCk aL1UMskdCNJCbdObuckYMUpznBzfV43O4sCUBe82VWLfOC6kgiwOCE0Y4k9X1pqLejZJ P9M0A+CPTLy4dquCLxTQijw6o15tfsnCUZ0aUw+c2YaIwjp3CPJJxrkrlxp/9A12SKvh 3MggeZxtfYb55gaI23XSzDnzsen4OK+FwcxlVaMz8I0K+q8ZwMReBTskatOWwMiV4sOt Ys34YvLop5YRZ6wVGEmJLcg1Hnp6OlmjnsfODpDRqTpih55nStVXuRbx1aI83gYrOllC K+ZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715877742; x=1716482542; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8dfDoFjby3SyG/aRSMt4bJnHeuy60vGajFgy+PGk0RM=; b=wopRhccDCTUufp+Bg0s8WYLVO+7AtTgPdetvgLVrxeJvR2Jqhz7IIf3KhWQPPdg5HD CgvSheCZepKNxg0T0gTuqd4t8mToQ52SApesrU70y3DCYyYInqLnur1nuQ8EASX1Ez0Z Ihh/WCXMde/pGdr6Nulzwn1t0gnNHJ0IrnrdhraD02aXnRgqUqkuyh3f/WWUYcWtm2bb agHMJ9Y8VdlR76Dv00fx3/OozvjQhTtWXOFiKAbjJfOM+GV2sYdxC9kZ5WRKggJawW1O Oig0U8ky6bGoS7UqILRyPfMGMXdpaHWIOWMT0naiaOY48CGXaOgLBNWFs30vInPVHRSp SSYw== X-Gm-Message-State: AOJu0YyAt5ZkZpono2tSEjJgTdjuSXzNuePbUKF5vBpQEBOJ6qeOB3UC 0h6C4y3YxLXQbMoNCiRbnb7C0RUjE9DcjYigzovmQU7YJRexN/bbjvKA1aUzhXvAMXZV1q1lLV6 HmF0LLFIxzEjGOraFwbYKkb8+zUECPu7bVP8p2YED9n/hCFJv6hlr+UUWJbXgHfn8y6LP2l06ee ETxq1SQtzUqEC7hZW5KE2VwBLFXQF2Wzaj1fE6kg5+ X-Google-Smtp-Source: AGHT+IHHSSq+yHl61xDILgBVZtLr68A2+EBy/A0zA/FYVAkD1jgORtv0oxqn9sts+GSSH2kJCM/fPQ== X-Received: by 2002:a17:907:7d8b:b0:a5a:669c:286b with SMTP id a640c23a62f3a-a5a669c290emr975549666b.19.1715877742286; Thu, 16 May 2024 09:42:22 -0700 (PDT) Received: from melexis ([91.192.181.19]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a5a1781d342sm1006647266b.6.2024.05.16.09.42.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 May 2024 09:42:22 -0700 (PDT) From: Volodymyr Kharuk To: Cc: Andrii Kyselov , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Laurent Pinchart , devicetree@vger.kernel.org, Hans Verkuil , Sakari Ailus , Benjamin Mugnier , Volodymyr Kharuk Subject: [PATCH v6 07/10] media: v4l: ctrls: Add user control base for mlx7502x Date: Thu, 16 May 2024 19:41:52 +0300 Message-Id: <4fa9a631f1435c799324cc5689e12f454ee6c904.1715871189.git.vkh@melexis.com> X-Mailer: git-send-email 2.38.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add a control base for mlx7502x and reserve 16 controls. Signed-off-by: Volodymyr Kharuk --- include/uapi/linux/v4l2-controls.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 3ac204818bdf..224a0f6b888c 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -216,6 +216,12 @@ enum v4l2_colorfx { */ #define V4L2_CID_USER_THP7312_BASE (V4L2_CID_USER_BASE + 0x11c0) +/* + * The base for Melexis ToF 7502x driver controls. + * We reserve 16 controls for this driver. + */ +#define V4L2_CID_USER_MLX7502X_BASE (V4L2_CID_USER_BASE + 0x11d0) + /* MPEG-class control IDs */ /* The MPEG controls are applicable to all codec controls * and the 'MPEG' part of the define is historical */ From patchwork Thu May 16 16:41:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Volodymyr Kharuk X-Patchwork-Id: 797402 Received: from mail-ej1-f49.google.com (mail-ej1-f49.google.com [209.85.218.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 018348F72 for ; Thu, 16 May 2024 16:42:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877748; cv=none; b=icmjwbkmIUps47vuTu/y2zZVUhwlpDqLHefptcEmwXfNG2PfiYYzsUlwD3RaxD2PEfkb36eZMxLGjrpFMazzr0dm8y3NnEAc5s8cBKdk9PE6SzdlHZkPkLCTaCKNsCl/GnHyJAljzrF8d8DNWCcV1RNtVyaRzUjN67XkQsLm+lY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877748; c=relaxed/simple; bh=60NwqEee69KTXbzH/fh5URBQh6l1wVZHZOdyJ1W2NC0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=pJLRwxqAtn8Op9u502l4eqfzrToxUS134HCEUbZ/I6UoLvKNRsmCgZW+7fV6aN/O/cKVzJBAXuHXpfinS7pRxwcG+CexFK7xIk2VV/wqXtrE1Xg5LGcQOC8lVpTpz8EqdGZ0BJM00VcgGcfNFa1XTFgsnuHgk3v0GRTb3iVFzf8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com; spf=pass smtp.mailfrom=melexis.com; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b=kaAE8Rh0; arc=none smtp.client-ip=209.85.218.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=melexis.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b="kaAE8Rh0" Received: by mail-ej1-f49.google.com with SMTP id a640c23a62f3a-a5a7d28555bso387627466b.1 for ; Thu, 16 May 2024 09:42:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=melexis.com; s=google; t=1715877745; x=1716482545; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=IJNnG7TgN52luijARGVw5REoqyl9hIWVUHwP2Y1Nhyk=; b=kaAE8Rh07bhM5L4LuuwO0Mb5doWn729J9gVrB0xxM75O2gBXCHguXFxn9cUMLSdAE+ sQ4VQ41/b5z7FYfVHAJS6rgEguG2awz8y7xUAlDt2/LOYGCk2uwgcq0L8cNOmm44DjKH NVPElWJ648A4/I/FuANm62EmK0VRJHQAnnIY2AlkY6NxHJ5iM4G3GPkl0m4qW+zpKQkL 3UBGFg/Tds++hR8rpou7qxYoDpzXOBEqrPDWkqVh3BayuBzdkPI1Ur5hT6qWC5X0ytAp 2NB6b1qQfymGa9C69NKC4TirMrE5d0XM5xhEikIzCKYe4YHMgXvAVCCsSmFby/kUkIKc mKlg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715877745; x=1716482545; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=IJNnG7TgN52luijARGVw5REoqyl9hIWVUHwP2Y1Nhyk=; b=Vv7ecosrydJTMmLwBOq4kwApbWUVZieUOiAwvFClo3GuA+USxA8uMPVkO5fWoq2bmH H6KyX/axFqKznOkGgDTykR1C1qLEvJHgJ33mpillcZKGiWZ+yiD3aAIFSrG84p0Pjj+s laF4KBYMEiQ3cZwlPwY+KeNBSES6Bw8A2aDC9Ud2wXkdVvCnSB4VMuHNPcm1ujagTmXH LlDs5IsRIk9I7Ozew0UlHtfZX2e149DtpMEpHkEsdKAKqhHpBuCIjyUsd2svQTQOyqLx 6Pdgg0nhxE63P+PbzPN8Em/abtc4//IW6Y1eu15E01nCjf7fAf7cRKcuXqQSwa/DfrCt aapg== X-Gm-Message-State: AOJu0YxsJfptmLARfeJGTnP52BfRzcY//Dnlialq4ogJx6DuCzg3lmJP g2jexdfZp2NCwBI/XPN5ayocNZNs3h0oPgKsqIKfCdeUVZtC/8mm6Sf8qKRv79td0CFbHPBIFOd o5sIx1thu7FROHljg0NMQCZLnLjYAe1bOHv/IFcbwVgfcqbV4rNVQ4sF6W01W4eEvMzR5niHHxk KV3TpEHoRKiAOPZ2ngfz37AnZyen8KxjScXjfcmJcU X-Google-Smtp-Source: AGHT+IGucIXNIT7sYuxR5kDX1N/vOtgMfoW9QG55n+j2IU1v+FyqavjxAqp9fJqWlKKx4Pm4Z/9Nlg== X-Received: by 2002:a17:906:a408:b0:a59:ba2b:5921 with SMTP id a640c23a62f3a-a5a2d67f991mr1233934066b.72.1715877745516; Thu, 16 May 2024 09:42:25 -0700 (PDT) Received: from melexis ([91.192.181.19]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a5cdd7f8ea1sm152730466b.109.2024.05.16.09.42.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 May 2024 09:42:25 -0700 (PDT) From: Volodymyr Kharuk To: Cc: Andrii Kyselov , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Laurent Pinchart , devicetree@vger.kernel.org, Hans Verkuil , Sakari Ailus , Benjamin Mugnier , Volodymyr Kharuk Subject: [PATCH v6 08/10] media: uapi: Add mlx7502x header file Date: Thu, 16 May 2024 19:41:53 +0300 Message-Id: <50375dfca35880bc8f6ebb47cfac92c738f4f192.1715871189.git.vkh@melexis.com> X-Mailer: git-send-email 2.38.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Define user controls for mlx7502x driver, add its documentation and update MAINTAINERS Signed-off-by: Volodymyr Kharuk --- .../userspace-api/media/drivers/index.rst | 1 + .../userspace-api/media/drivers/mlx7502x.rst | 28 +++++++++++++++++++ MAINTAINERS | 2 ++ include/uapi/linux/mlx7502x.h | 28 +++++++++++++++++++ 4 files changed, 59 insertions(+) create mode 100644 Documentation/userspace-api/media/drivers/mlx7502x.rst create mode 100644 include/uapi/linux/mlx7502x.h diff --git a/Documentation/userspace-api/media/drivers/index.rst b/Documentation/userspace-api/media/drivers/index.rst index 2252063593bf..55d199942636 100644 --- a/Documentation/userspace-api/media/drivers/index.rst +++ b/Documentation/userspace-api/media/drivers/index.rst @@ -33,6 +33,7 @@ For more details see the file COPYING in the source distribution of Linux. dw100 imx-uapi max2175 + mlx7502x npcm-video omap3isp-uapi st-vgxy61 diff --git a/Documentation/userspace-api/media/drivers/mlx7502x.rst b/Documentation/userspace-api/media/drivers/mlx7502x.rst new file mode 100644 index 000000000000..d68506c09f84 --- /dev/null +++ b/Documentation/userspace-api/media/drivers/mlx7502x.rst @@ -0,0 +1,28 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Melexis mlx7502x ToF camera sensor driver +========================================= + +The mlx7502x driver implements the following driver-specific controls: + +``V4L2_CID_MLX7502X_OUTPUT_MODE (menu)`` +---------------------------------------- + The sensor has two taps, which gather reflected light: A and B. + The control sets the way data should be put in a buffer. The most + common output mode is A-B which provides the best sunlight robustness. + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 4 + + * - ``V4L2_MLX7502X_OUTPUT_MODE_A_MINUS_B`` + - tap A minus tap B + * - ``V4L2_MLX7502X_OUTPUT_MODE_A_PLUS_B`` + - tap A plus tap B + * - ``V4L2_MLX7502X_OUTPUT_MODE_A`` + - only tap A + * - ``V4L2_MLX7502X_OUTPUT_MODE_B`` + - only tap B + * - ``V4L2_MLX7502X_OUTPUT_MODE_A_AND_B`` + - tap A and tap B (this config will change PAD format) diff --git a/MAINTAINERS b/MAINTAINERS index de46c28bb3f2..8fd282ec18dc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14017,7 +14017,9 @@ M: Volodymyr Kharuk L: linux-media@vger.kernel.org S: Supported W: http://www.melexis.com +F: Documentation/userspace-api/media/drivers/mlx7502x.rst F: Documentation/userspace-api/media/v4l/ext-ctrls-tof.rst +F: include/uapi/linux/mlx7502x.h MELFAS MIP4 TOUCHSCREEN DRIVER M: Sangwon Jee diff --git a/include/uapi/linux/mlx7502x.h b/include/uapi/linux/mlx7502x.h new file mode 100644 index 000000000000..80e9317ff0fc --- /dev/null +++ b/include/uapi/linux/mlx7502x.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Melexis 7502x ToF cameras driver. + * + * Copyright (C) 2021 Melexis N.V. + * + */ + +#ifndef __UAPI_MLX7502X_H_ +#define __UAPI_MLX7502X_H_ + +#include + +/* + * this is related to the taps in ToF cameras, + * usually A minus B is the best option + */ +enum v4l2_mlx7502x_output_mode { + V4L2_MLX7502X_OUTPUT_MODE_A_MINUS_B = 0, + V4L2_MLX7502X_OUTPUT_MODE_A_PLUS_B, + V4L2_MLX7502X_OUTPUT_MODE_A, + V4L2_MLX7502X_OUTPUT_MODE_B, + V4L2_MLX7502X_OUTPUT_MODE_A_AND_B, /* output frame size doubles */ +}; + +#define V4L2_CID_MLX7502X_OUTPUT_MODE (V4L2_CID_USER_MLX7502X_BASE + 0) + +#endif /* __UAPI_MLX7502X_H_ */ From patchwork Thu May 16 16:41:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Volodymyr Kharuk X-Patchwork-Id: 797593 Received: from mail-ej1-f43.google.com (mail-ej1-f43.google.com [209.85.218.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 28D748F72 for ; Thu, 16 May 2024 16:42:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877751; cv=none; b=a6q9d7zfxOOD3fRd7fwwbsMElMeuef0W2cHUPiUm6nXG1UKaLqjiGXd/MwmxKiyCQz4OsPxLEyyX1Z7PfrXqcQTCkuZUqpxj9UILxo+1sO4Wpz6ecmHsQYeRFKRNn8CliGxnw+4HCCxiqgD2/MwrikIXJGUZ10MRIYGJeEXKUBI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877751; c=relaxed/simple; bh=qF09e4Yv7GpDkghetabxRfrKKsh5ptgSWxf8gO4YBvE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=rLlYLD784NsNndFR9l4pmOeEc9eCcbctPVOCz7WgP6eJxWXDxnDrVS3IoTqgMfO730fcHYhzwDsoJZobjTs9Wiqe31iTNqsf5lOxDtC8Jurw3/GmRYVbZq6cMRpWpziYKgbBb1qhFj9yL51OMe7Fdpxtzw2b8exq+8BUX7Y+T8I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com; spf=pass smtp.mailfrom=melexis.com; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b=Su9o7h43; arc=none smtp.client-ip=209.85.218.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=melexis.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b="Su9o7h43" Received: by mail-ej1-f43.google.com with SMTP id a640c23a62f3a-a59ad344f7dso276238366b.0 for ; Thu, 16 May 2024 09:42:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=melexis.com; s=google; t=1715877748; x=1716482548; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=EUku4Fwzj8r03nJASY3i7hrjy3KpdcN95EIZyP4+4HA=; b=Su9o7h433ebuOjPljcxHqltNnh8egzvBTafQsYmKYc8dFLy/p+HcKwoFLVgRs/G0js TQsWW/V4TDy7HhX+MLG4jUdYgb4R509SYpqzBoKW7ClgXoJ50MIaNFLQPhRVIKgHgVGT +4Kd8I6aRnJYYKowAZdPDTne75igLTQ04mrablros0fs/t5X5CugqdSQsOZZMP5XaCjf xlarxjxsoY9/aoSKM3Mko4myCajgVT297QmfAIoEtCGXHibQTbIaSYxG5EfU6OeTuxxd oZUEYVoAns6lgoBOh9M3yOTXoMF+q+Z/iKY7gQ+GoQCTZKqmFmVuhDgNMAsilLrMrvQD bxCQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715877748; x=1716482548; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=EUku4Fwzj8r03nJASY3i7hrjy3KpdcN95EIZyP4+4HA=; b=jfoRA677kGlDq/7QCOiCVYsicd6iz8S8HU9MEJtC8UA9zP6eNIZrzpg6nYgUuiDd1a bApKX9GUG+AXdtR1IXsoyCoTqO+iGWMkGXw1TINK0KEBJwCqvnyRShnU0z3eGLDeh8a8 jXdhTd/iotiOZRkmpcRg8rz65XlyEVHOC3QRZOcKoO3Xm2lX5wCpOCEN2eRs2vg/q9CG SiOhdYk8ncWjz1+cmVW+ybRL/lFt1DlHN4xsyRY6ALi9VUAM9645jwVt27XJz+C56VT/ 1qm16SY+fu6ne9N9+lSmaiN4Sw7g0157Qs40bVfdsP2UrxRFFhzRkoquACxK7VsQRlXd mjHw== X-Gm-Message-State: AOJu0Yx5CABSgLV3o+wkBktEsWJDXRDW2lDt1CQInt4UwPXOU+McdtNf gyXNumigFapsCIJS/piaermOAL4hZCdLpoS3YsZ5AY09f52xYZddyAaLAqw5SLOb4nsn/lwDwcB wa2VYgIIsnrr6bExpSntNyLoUI/xlepR2lluqG1LFEXH3CJB11Rvasg+JPNxjT/HCq5dKPWxGIX j4B7JvIx6zElnMNHV11MyT8H3NHFsN3iN3Hde95hy+ X-Google-Smtp-Source: AGHT+IGmKe5n9r/KMIy/YGQOL6TUNBLUMkWW6sojgBAEfMyEvqbDw9L+4dfmYWWR4DSYB5hVq2c1/A== X-Received: by 2002:a17:906:6a15:b0:a59:c46b:c529 with SMTP id a640c23a62f3a-a5a2d3cb713mr1492630166b.0.1715877748592; Thu, 16 May 2024 09:42:28 -0700 (PDT) Received: from melexis ([91.192.181.19]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a5a17b01647sm996744866b.160.2024.05.16.09.42.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 May 2024 09:42:28 -0700 (PDT) From: Volodymyr Kharuk To: Cc: Andrii Kyselov , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Laurent Pinchart , devicetree@vger.kernel.org, Hans Verkuil , Sakari Ailus , Benjamin Mugnier , Volodymyr Kharuk , Krzysztof Kozlowski Subject: [PATCH v6 09/10] media: dt-bindings: Add mlx7502x camera sensor Date: Thu, 16 May 2024 19:41:54 +0300 Message-Id: <2c47fdf59c79f52f49b8cf1f208d16fed5494b66.1715871189.git.vkh@melexis.com> X-Mailer: git-send-email 2.38.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add device tree binding of the mlx7502x and update MAINTAINERS Signed-off-by: Volodymyr Kharuk Reviewed-by: Krzysztof Kozlowski --- .../bindings/media/i2c/melexis,mlx7502x.yaml | 126 ++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 127 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/melexis,mlx7502x.yaml diff --git a/Documentation/devicetree/bindings/media/i2c/melexis,mlx7502x.yaml b/Documentation/devicetree/bindings/media/i2c/melexis,mlx7502x.yaml new file mode 100644 index 000000000000..7b86b6c5b151 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/melexis,mlx7502x.yaml @@ -0,0 +1,126 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/i2c/melexis,mlx7502x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Melexis ToF 7502x MIPI CSI-2 Sensor + +maintainers: + - Volodymyr Kharuk + +description: |- + Melexis ToF 7502x sensors has a CSI-2 output. It supports 2 and 4 lanes, + and mipi speeds are 300, 600, 704, 800, 904, 960Mbs. Supported format is RAW12. + Sensor 75026 is QVGA, while 75027 is VGA sensor. + +properties: + compatible: + enum: + - melexis,mlx75026 + - melexis,mlx75027 + + reg: + maxItems: 1 + + clocks: + description: Clock frequency 8MHz + maxItems: 1 + + vdda-supply: + description: + Analog power supply(2.7V). + + vddif-supply: + description: + Interface power supply(1.8V). + + vddd-supply: + description: + Digital power supply(1.2V). + + vdmix-supply: + description: + Mixed driver power supply(1.2V). + + reset-gpios: + maxItems: 1 + description: Reset Sensor GPIO Control (active low) + + port: + description: MIPI CSI-2 transmitter port + $ref: /schemas/graph.yaml#/$defs/port-base + + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + oneOf: + - items: + - const: 1 + - const: 2 + - items: + - const: 1 + - const: 2 + - const: 3 + - const: 4 + + required: + - data-lanes + - link-frequencies + +required: + - compatible + - reg + - clocks + - port + - vdda-supply + - vddif-supply + - vddd-supply + - vdmix-supply + +additionalProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + mlx7502x: camera@57 { + compatible = "melexis,mlx75027"; + reg = <0x57>; + clocks = <&mlx7502x_clk>; + + assigned-clocks = <&mlx7502x_clk>; + assigned-clock-parents = <&mlx7502x_clk_parent>; + assigned-clock-rates = <8000000>; + + vdda-supply = <®_2v7>; + vddif-supply = <®_1v8>; + vddd-supply = <®_1v2>; + vdmix-supply = <®_1v2>; + + reset-gpios = <&gpio_exp 6 GPIO_ACTIVE_HIGH>; + + port { + mlx7502x_out_mipi_csi2: endpoint { + remote-endpoint = <&mipi_csi2_from_mlx7502x>; + data-lanes = <1 2 3 4>; + link-frequencies = /bits/ 64 < 960000000 + 904000000 + 800000000 + 704000000 + 600000000 + 300000000 >; + }; + }; + }; + }; + +... diff --git a/MAINTAINERS b/MAINTAINERS index 8fd282ec18dc..02a764f52a55 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14017,6 +14017,7 @@ M: Volodymyr Kharuk L: linux-media@vger.kernel.org S: Supported W: http://www.melexis.com +F: Documentation/devicetree/bindings/media/i2c/melexis,mlx7502x.yaml F: Documentation/userspace-api/media/drivers/mlx7502x.rst F: Documentation/userspace-api/media/v4l/ext-ctrls-tof.rst F: include/uapi/linux/mlx7502x.h From patchwork Thu May 16 16:41:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Volodymyr Kharuk X-Patchwork-Id: 797401 Received: from mail-ed1-f48.google.com (mail-ed1-f48.google.com [209.85.208.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A00EB2555B for ; Thu, 16 May 2024 16:42:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877757; cv=none; b=MdIMm1GmSnehwz/uaMmk/ZzzPMiptDm61e8Lo6yfKRyOeN5q1jgkDXzgjrYXYQ46Y/Tb6mh+RlpFcJSIxf10f1JPKDLLz6iOTtD0v9p4VPmIbB1U2fFQfgkNm25A2CF2wm1D76YIjRNBiAZ4pjkGMcPLdx1WrgXP4vIsTcREnpE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715877757; c=relaxed/simple; bh=PI6SvEixWsR8hbw5BleXYLFMTxMv+toVxmVS3ZfMoTU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=TbnAOfbcR9wume1uYNMGyDWc1EkqL8jfPT+SsazmvmyAouq5rAFS2T2WyIYYSaRrkUspiT4aDqfMl9BR0bD7puV/JqLnIUGQ2L7Y5eTpIkd9yRvigmoSJfjTxLc0RP1ITLK1w4uu1zK/tCXWbLtLg84L/2f/txQXvBcpQSvsuk8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com; spf=pass smtp.mailfrom=melexis.com; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b=BIS1yMNA; arc=none smtp.client-ip=209.85.208.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=melexis.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=melexis.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=melexis.com header.i=@melexis.com header.b="BIS1yMNA" Received: by mail-ed1-f48.google.com with SMTP id 4fb4d7f45d1cf-5727dc6d3edso3850255a12.0 for ; Thu, 16 May 2024 09:42:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=melexis.com; s=google; t=1715877752; x=1716482552; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=NtTjwSi4VA+sb3NMv06I65rJzKpWdemNR6sEYZYa+Co=; b=BIS1yMNAE0ypQLa1Utk5yvAsibbKnsmWn0H1pybmiEL3yzZ4sky9uZp2211ZpYq/H+ Db8hiBxqogiLsZbRaZdFjqqTJodtNDm3JB5Yk20zAUysB0IikoBemou+nrpA6ya/rfRG FjbFQ1LzNSMMKjNleGWn46Inu1GwNdipssFHVZDwMd72dsI5zOwot9xkTHIUJGWAHJWL ZrMVrrvX3vgEuhCxwSG0LmeArfptBvNcNiyTOk0zXodSuHEkKhOZtu+uDx8vkr5NyFlL fj1/qHax6s/fAktMtrlUXNGXuRT2wZRGupuqS2CBTtQCOxdL1W21eR94TPSWxtjpw1W6 VONQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715877752; x=1716482552; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NtTjwSi4VA+sb3NMv06I65rJzKpWdemNR6sEYZYa+Co=; b=DdGc0CndlHCFTCGcoaHV2VAxu7Kfi4UgZipanzdAq/o+n6+je7c1xEg8T20AXoNVpX 9aN8Al1nR3SrZmfBMJa07id4r7nd395nIofazkTLMT5Eo/M+Z2kt00v97bs5F0bi7ZL3 ySg6SMiI2c6e6PHMsCCAjbltV69d5C98+whSADRaWS00XUPp19IxpRBCGx2wpONIYD9G J2tte/iWYSmgDB3l7bkrxRc+3MsGd7r+Ji2efIbDmP5EOGaXnjFwRCsyo+opz2PqyxzQ 8NsvuS77rxKXLljoJJMnZtfOvBxsul5wWqvLsMudy6Q2e+lMSWBpm706HiIZ0nAsUc5a j03w== X-Gm-Message-State: AOJu0YyZoS6jRzCiuDZRwrnAz6oOwQZDgsbaXhVJWJ7mhdmSw9KqpBRm 6np2CP+dPmC9cAbLJCW01roy/bBLbw5d8w1nL/Dq1cukEhrUdHrpWwNWBr5i8Xw07ULOWtbCsy1 CFipE9e7/MFMlv0r9OvoQpNmHtje93Cn3uzYDTZahQtJ0rhsOKunKlT/PysRnaWiIUf9Ik7UWSj 5aKRs2669rTuWqF+a47qlZuUbRhSNeqnzBc7Y9TiB3 X-Google-Smtp-Source: AGHT+IFtF3DKUtQRI+/+oQwBpZkq/JUIqSUoxBz8xOO/zOkLz+37iBFga5AbY+Gkmacg7YRxxrs9MA== X-Received: by 2002:a50:8e59:0:b0:566:4aa9:7143 with SMTP id 4fb4d7f45d1cf-5734d5be334mr13064490a12.14.1715877751764; Thu, 16 May 2024 09:42:31 -0700 (PDT) Received: from melexis ([91.192.181.19]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5733bea651asm10586477a12.11.2024.05.16.09.42.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 May 2024 09:42:31 -0700 (PDT) From: Volodymyr Kharuk To: Cc: Andrii Kyselov , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Laurent Pinchart , devicetree@vger.kernel.org, Hans Verkuil , Sakari Ailus , Benjamin Mugnier , Volodymyr Kharuk Subject: [PATCH v6 10/10] media: i2c: Add driver for mlx7502x ToF sensor Date: Thu, 16 May 2024 19:41:55 +0300 Message-Id: <6f666d475da17b3469fd0471531bc615f6fd797a.1715871189.git.vkh@melexis.com> X-Mailer: git-send-email 2.38.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Melexis ToF 7502x sensors has a CSI-2 output. It supports 2 and 4 lanes, and mipi speeds are 300, 600, 704, 800, 904, 960Mbs. Supported format is RAW12. Sensor 75026 is QVGA, while 75027 is VGA sensor. The driver supports: - Digital binning and cropping - Horizontal and vertical flip - phase shifts(up to 8) - frequency modulation - time integration - single trigger mode Signed-off-by: Volodymyr Kharuk Signed-off-by: Andrii Kyselov --- MAINTAINERS | 1 + drivers/media/i2c/Kconfig | 13 + drivers/media/i2c/Makefile | 1 + drivers/media/i2c/mlx7502x.c | 1845 ++++++++++++++++++++++++++++++++++ 4 files changed, 1860 insertions(+) create mode 100644 drivers/media/i2c/mlx7502x.c diff --git a/MAINTAINERS b/MAINTAINERS index 02a764f52a55..9cd630ef89d4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14020,6 +14020,7 @@ W: http://www.melexis.com F: Documentation/devicetree/bindings/media/i2c/melexis,mlx7502x.yaml F: Documentation/userspace-api/media/drivers/mlx7502x.rst F: Documentation/userspace-api/media/v4l/ext-ctrls-tof.rst +F: drivers/media/i2c/mlx7502x.c F: include/uapi/linux/mlx7502x.h MELFAS MIP4 TOUCHSCREEN DRIVER diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index c6d3ee472d81..3199a9be4d5e 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -236,6 +236,19 @@ config VIDEO_IMX415 config VIDEO_MAX9271_LIB tristate +config VIDEO_MLX7502X + tristate "Melexis ToF 75026 and 75027 sensors support" + depends on I2C && VIDEO_DEV + select MEDIA_CONTROLLER + select VIDEO_V4L2_SUBDEV_API + select V4L2_FWNODE + help + This is a V4L2 sensor driver for the Melexis 75026 and 75027 + ToF sensors. + + To compile this driver as a module, choose M here: the + module will be called mlx7502x. + config VIDEO_MT9M001 tristate "mt9m001 support" help diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index dfbe6448b549..d87f4d8e7284 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -65,6 +65,7 @@ obj-$(CONFIG_VIDEO_M52790) += m52790.o obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o obj-$(CONFIG_VIDEO_MAX9286) += max9286.o obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o +obj-$(CONFIG_VIDEO_MLX7502X) += mlx7502x.o obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o obj-$(CONFIG_VIDEO_MT9M111) += mt9m111.o diff --git a/drivers/media/i2c/mlx7502x.c b/drivers/media/i2c/mlx7502x.c new file mode 100644 index 000000000000..4843c3f39e7a --- /dev/null +++ b/drivers/media/i2c/mlx7502x.c @@ -0,0 +1,1845 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * A V4L2 driver for Melexis 7502x ToF cameras. + * + * Copyright (C) 2022 Melexis N.V. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MLX7502X_PARAM_HOLD_REG 0x0102 +#define MLX7502X_HMAX_REG 0x0800 +#define MLX7502X_COLUMN_START_REG 0x0804 +#define MLX7502X_COLUMN_LEN_REG 0x0806 +#define MLX7502X_ROW_START_REG 0x0808 +#define MLX7502X_ROW_END_REG 0x080a +#define MLX7502X_VFLIP_REG 0x080c +#define MLX7502X_HFLIP_REG 0x080d +#define MLX7502X_OUTPUT_MODE_REG 0x0828 +#define MLX7502X_STREAM_EN_REG 0x1001 +#define MLX7502X_DATA_LANE_CONFIG_REG 0x1010 +#define MLX7502X_FMOD_REG 0x1048 +#define MLX7502X_PLL_RES_REG 0x104b +#define MLX7502X_BINNING_REG 0x14a5 +#define MLX7502X_CONTINUOUS_REG 0x1c40 +#define MLX7502X_SW_TRIGGER_REG 0x2100 +#define MLX7502X_FRAME_TIME_REG 0x2108 +#define MLX7502X_TINT0_REG 0x2120 +#define MLX7502X_PX_PHASE_SHIFT_REG 0x21b4 +#define MLX7502X_DIVSELPRE_REG 0x21be +#define MLX7502X_DIVSEL_REG 0x21bf +#define MLX7502X_PHASE_COUNT_REG 0x21e8 +#define MLX7502X_PLLSETUP_REG 0x4010 +#define MLX7502X_PRETIME_REG 0x4015 +#define MLX7502X_RANDNM0_REG 0x5265 + +#define MLX7502X_SW_TRIGGER_DEFAULT 0x0000 +#define MLX7502X_SW_TRIGGER_TRIG 0x0001 +#define MLX7502X_SW_TRIGGER_CONT 0x0008 + +#define MLX7502X_NIBLE_LOW_MASK GENMASK(3, 0) +#define MLX7502X_NIBLE_HIGH_MASK GENMASK(7, 4) + +#define MLX7502X_PHASE_MAX_NUM 8 + +#define MLX7502X_CLK_RATE_MHZ 120 +#define MLX7502X_XCLK_RATE (8 * HZ_PER_MHZ) + +#define MLX7502X_RESET_DELAY_MS 100 +#define MLX7502X_STREAMING_DELAY_MS 2 + +#define MLX7502X_LINK_FREQ_REG_N 8 +#define MLX7502X_LINK_FREQ_N 6 +#define MLX7502X_LANE_N 2 +#define MLX7502X_OUTPUT_MODE_N 2 + +#define MLX7502X_PLLSETUP_US 503 +#define MLX7502X_PLLSETUP_TICKS 8 +#define MLX7502X_PRETIME_US 50 +#define MLX7502X_FRAME_ADD_TICKS 13 + +#define MLX7502X_DEFAULT_FRAME_RATE 25 + +#define MLX7502X_ROW_START(top) ((top) / 2) +#define MLX7502X_ROW_END(top, height) ((((top) + (height)) / 2) + 1) + +#define MLX7502X_LEFT_ALIGN 0 +#define MLX7502X_LEFT_MIN 0 + +#define MLX7502X_TOP_ALIGN 1 +#define MLX7502X_TOP_MIN 0 + +#define MLX7502X_PLL_RES_THR 113 + +static const char * const mlx7502x_supply_names[] = { + "vdda", /* Analog (2.7V) supply */ + "vddif", /* I/O (1.8V) supply */ + "vddd", /* Digital core (1.2V) supply */ + "vdmix", /* MIX driver (1.2V) supply */ +}; + +#define MLX7502X_NUM_SUPPLIES ARRAY_SIZE(mlx7502x_supply_names) + +struct mlx7502x_regval_list { + u16 addr; + u8 data; +}; + +struct mlx7502x_link_freq_list { + s64 link_freq[MLX7502X_LINK_FREQ_N]; + u16 addr[MLX7502X_LINK_FREQ_REG_N]; + u8 data[MLX7502X_LANE_N][MLX7502X_LINK_FREQ_N][MLX7502X_LINK_FREQ_REG_N]; + u16 hmax[MLX7502X_LANE_N][MLX7502X_LINK_FREQ_N][MLX7502X_OUTPUT_MODE_N]; +}; + +struct mlx7502x_binning_mode { + u8 reg_value; + u8 ratio; + u8 width_align; + u8 height_align; + u8 width_min; + u8 height_min; +}; + +struct mlx7502x_output_mode { + u8 hmax_index; + u8 width_mult; +}; + +/* configuration of divider for specific fmod */ +struct mlx7502x_fmod_list { + u32 fmod; + u8 divselpre; + u8 divsel; +}; + +struct mlx7502x_sensor_desc { + const struct mlx7502x_regval_list *init_cfg; + u32 init_cfg_size; + const struct mlx7502x_link_freq_list *link_freq_cfg; + u32 width; + u32 height; +}; + +struct mlx7502x { + struct v4l2_subdev sd; + struct media_pad pad; + struct v4l2_fwnode_endpoint ep; + struct device *dev; + + /* controls */ + struct v4l2_ctrl_handler ctrl_handler; + struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *trigger; + struct v4l2_ctrl *trigger_mode; + struct v4l2_ctrl *tint; + struct v4l2_ctrl *phase_seq; + struct v4l2_ctrl *output_mode; + + struct clk *xclk; + struct regulator_bulk_data supplies[MLX7502X_NUM_SUPPLIES]; + + /* pins */ + struct gpio_desc *reset; + + const struct mlx7502x_sensor_desc *cur_desc; + const struct mlx7502x_binning_mode *binning_mode; + int streaming; + u16 hmax; /* internal sensor frame size in ticks */ +}; + +static const struct mlx7502x_regval_list mlx7502x_common_init_cfg[] = { + { 0x1006, 0x08 }, { 0x1007, 0x00 }, { 0x1040, 0x00 }, { 0x1041, 0x96 }, + { 0x1042, 0x01 }, { 0x1043, 0x00 }, { 0x1044, 0x00 }, { 0x1046, 0x01 }, + { 0x104a, 0x01 }, { 0x1000, 0x00 }, { 0x10d3, 0x10 }, { 0x1448, 0x06 }, + { 0x1449, 0x40 }, { 0x144a, 0x06 }, { 0x144b, 0x40 }, { 0x144c, 0x06 }, + { 0x144d, 0x40 }, { 0x144e, 0x06 }, { 0x144f, 0x40 }, { 0x1450, 0x06 }, + { 0x1451, 0x40 }, { 0x1452, 0x06 }, { 0x1453, 0x40 }, { 0x1454, 0x06 }, + { 0x1455, 0x40 }, { 0x1456, 0x06 }, { 0x1457, 0x40 }, { 0x2203, 0x1e }, + { 0x2c08, 0x01 }, { 0x3c2b, 0x1b }, { 0x400e, 0x01 }, { 0x400f, 0x81 }, + { 0x40d1, 0x00 }, { 0x40d2, 0x00 }, { 0x40d3, 0x00 }, { 0x40db, 0x3f }, + { 0x40de, 0x40 }, { 0x40df, 0x01 }, { 0x4134, 0x04 }, { 0x4135, 0x04 }, + { 0x4136, 0x04 }, { 0x4137, 0x04 }, { 0x4138, 0x04 }, { 0x4139, 0x04 }, + { 0x413a, 0x04 }, { 0x413b, 0x04 }, { 0x413c, 0x04 }, { 0x4146, 0x01 }, + { 0x4147, 0x01 }, { 0x4148, 0x01 }, { 0x4149, 0x01 }, { 0x414a, 0x01 }, + { 0x414b, 0x01 }, { 0x414c, 0x01 }, { 0x414d, 0x01 }, { 0x4158, 0x01 }, + { 0x4159, 0x01 }, { 0x415a, 0x01 }, { 0x415b, 0x01 }, { 0x415c, 0x01 }, + { 0x415d, 0x01 }, { 0x415e, 0x01 }, { 0x415f, 0x01 }, { 0x4590, 0x00 }, + { 0x4591, 0x2e }, { 0x4684, 0x00 }, { 0x4685, 0xa0 }, { 0x4687, 0xa1 }, + { 0x471e, 0x07 }, { 0x471f, 0xc9 }, { 0x473a, 0x07 }, { 0x473b, 0xc9 }, + { 0x4770, 0x00 }, { 0x4771, 0x00 }, { 0x4772, 0x1f }, { 0x4773, 0xff }, + { 0x4778, 0x06 }, { 0x4779, 0xa4 }, { 0x477a, 0x07 }, { 0x477b, 0xae }, + { 0x4788, 0x06 }, { 0x4789, 0xa4 }, { 0x478c, 0x1f }, { 0x478d, 0xff }, + { 0x478e, 0x00 }, { 0x478f, 0x00 }, { 0x4792, 0x00 }, { 0x4793, 0x00 }, + { 0x4796, 0x00 }, { 0x4797, 0x00 }, { 0x479a, 0x00 }, { 0x479b, 0x00 }, + { 0x479c, 0x1f }, { 0x479d, 0xff }, { 0x479e, 0x00 }, { 0x479f, 0x00 }, + { 0x47a2, 0x00 }, { 0x47a3, 0x00 }, { 0x47a6, 0x00 }, { 0x47a7, 0x00 }, + { 0x47aa, 0x00 }, { 0x47ab, 0x00 }, { 0x47ac, 0x1f }, { 0x47ad, 0xff }, + { 0x47ae, 0x00 }, { 0x47af, 0x00 }, { 0x47b2, 0x00 }, { 0x47b3, 0x00 }, + { 0x47b6, 0x00 }, { 0x47b7, 0x00 }, { 0x47ba, 0x00 }, { 0x47bb, 0x00 }, + { 0x47bc, 0x1f }, { 0x47bd, 0xff }, { 0x47be, 0x00 }, { 0x47bf, 0x00 }, + { 0x47c2, 0x00 }, { 0x47c3, 0x00 }, { 0x47c6, 0x00 }, { 0x47c7, 0x00 }, + { 0x47ca, 0x00 }, { 0x47cb, 0x00 }, { 0x4834, 0x00 }, { 0x4835, 0xa0 }, + { 0x4837, 0xa1 }, { 0x4878, 0x00 }, { 0x4879, 0xa0 }, { 0x487b, 0xa1 }, + { 0x48bc, 0x00 }, { 0x48bd, 0xa0 }, { 0x48bf, 0xa1 }, { 0x49ff, 0x78 }, + { 0x4baf, 0x1a }, { 0x4bc7, 0x1a }, { 0x4d2a, 0x07 }, { 0x4d80, 0x06 }, + { 0x4d81, 0xa4 }, { 0x4d82, 0x07 }, { 0x4e39, 0x07 }, { 0x4e7b, 0x64 }, + { 0x4e8e, 0x0e }, { 0x4e9c, 0x01 }, { 0x4ea0, 0x01 }, { 0x4ea1, 0x03 }, + { 0x4ea5, 0x00 }, { 0x4ea7, 0x00 }, { 0x4f05, 0x04 }, { 0x4f0d, 0x04 }, + { 0x4f15, 0x04 }, { 0x4f19, 0x01 }, { 0x4f20, 0x01 }, { 0x4f66, 0x0f }, + { 0x500f, 0x01 }, { 0x5225, 0x2f }, { 0x5227, 0x1e }, { 0x5231, 0x19 }, + { 0x5245, 0x07 }, { 0x5252, 0x07 }, { 0x5253, 0x08 }, { 0x5254, 0x07 }, + { 0x5255, 0xb4 }, { 0x5272, 0x04 }, { 0x5273, 0x2e }, { 0x5282, 0x04 }, + { 0x5283, 0x2e }, { 0x5286, 0x00 }, { 0x5287, 0x5d }, { 0x1433, 0x00 }, + { 0x3c18, 0x00 }, { 0x100e, 0x00 }, { 0x100f, 0x00 } +}; + +static const struct mlx7502x_regval_list mlx7502x_75027_init_cfg[] = { + { 0x477d, 0xd6 }, { 0x4954, 0x00 }, { 0x4955, 0xa0 }, { 0x4957, 0xa1 }, + { 0x4984, 0x00 }, { 0x4985, 0xa0 }, { 0x4987, 0xa1 }, { 0x49b9, 0x78 }, + { 0x49c3, 0x3c }, { 0x49c9, 0x76 }, { 0x49d3, 0x3f }, { 0x49dc, 0x00 }, + { 0x49dd, 0xa0 }, { 0x49df, 0xa1 }, { 0x49ef, 0x78 }, { 0x49f9, 0x3c }, + { 0x4a05, 0x3c }, { 0x4a0b, 0x76 }, { 0x4a11, 0x3f }, { 0x4a1a, 0x00 }, + { 0x4a1b, 0xa0 }, { 0x4a1d, 0xa1 }, { 0x4a1f, 0x78 }, { 0x4a29, 0x3c }, + { 0x4a4a, 0x00 }, { 0x4a4b, 0xa0 }, { 0x4a4d, 0xa1 }, { 0x4a7a, 0x00 }, + { 0x4a7b, 0xa0 }, { 0x4a7d, 0xa1 }, { 0x4aee, 0x00 }, { 0x4aef, 0xa0 }, + { 0x4af1, 0xa1 }, { 0x4b2e, 0x00 }, { 0x4b2f, 0xa0 }, { 0x4b31, 0xa1 }, + { 0x4b5a, 0x00 }, { 0x4b5b, 0xa0 }, { 0x4b5d, 0xa1 }, { 0x4b86, 0x00 }, + { 0x4b87, 0xa0 }, { 0x4b89, 0xa1 }, { 0x4b9f, 0x1a }, { 0x4bb7, 0x1a }, + { 0x4bcf, 0x1a }, { 0x4bee, 0x00 }, { 0x4bef, 0xa0 }, { 0x4bf1, 0xa1 }, + { 0x4bf7, 0x1a }, { 0x4c01, 0x1a }, { 0x4c58, 0x00 }, { 0x4c59, 0xa0 }, + { 0x4c5b, 0xa1 }, { 0x4c6e, 0x00 }, { 0x4c6f, 0xa0 }, { 0x4c71, 0xa1 }, + { 0x4c7a, 0x01 }, { 0x4c7b, 0x35 }, { 0x4cf2, 0x07 }, { 0x4cf3, 0xc9 }, + { 0x4cf8, 0x06 }, { 0x4cf9, 0x9b }, { 0x4cfa, 0x07 }, { 0x4cfb, 0xae }, + { 0x4cfe, 0x07 }, { 0x4cff, 0xc9 }, { 0x4d04, 0x06 }, { 0x4d05, 0x98 }, + { 0x4d06, 0x07 }, { 0x4d07, 0xb1 }, { 0x4d18, 0x06 }, { 0x4d19, 0xa4 }, + { 0x4d1a, 0x07 }, { 0x4d1b, 0x49 }, { 0x4d1e, 0x07 }, { 0x4d1f, 0xc9 }, + { 0x4d2b, 0xc9 }, { 0x4d4a, 0x07 }, { 0x4d4b, 0xc9 }, { 0x4d50, 0x06 }, + { 0x4d51, 0x9b }, { 0x4d52, 0x07 }, { 0x4d53, 0xae }, { 0x4d56, 0x07 }, + { 0x4d57, 0xc9 }, { 0x4d5c, 0x06 }, { 0x4d5d, 0x98 }, { 0x4d5e, 0x07 }, + { 0x4d5f, 0xb1 }, { 0x4d70, 0x06 }, { 0x4d71, 0xa4 }, { 0x4d72, 0x07 }, + { 0x4d73, 0x49 }, { 0x4d78, 0x06 }, { 0x4d79, 0xa4 }, { 0x4d7a, 0x07 }, + { 0x4d7b, 0xae }, { 0x4d7c, 0x1f }, { 0x4d7d, 0xff }, { 0x4d7e, 0x1f }, + { 0x4d7f, 0xff }, { 0x4d83, 0xae }, { 0x4d84, 0x1f }, { 0x4d85, 0xff }, + { 0x4d86, 0x1f }, { 0x4d87, 0xff }, +}; + +static const struct mlx7502x_link_freq_list mlx75027_link_freq_cfg = { + .link_freq = { + 300000000, + 600000000, + 704000000, + 800000000, + 904000000, + 960000000 + }, + .addr = { + 0x100c, 0x100d, 0x1016, 0x1017, 0x1045, 0x1047, 0x1060, 0x1071 + }, + .data = { + { /* lane 2 */ + /* 300MBps */ + { 0x02, 0x58, 0x09, 0x99, 0x4b, 0x02, 0x01, 0x0c }, + /* 600MBps */ + { 0x04, 0xb0, 0x04, 0xcc, 0x4b, 0x02, 0x00, 0x06 }, + /* 704MBps */ + { 0x05, 0x80, 0x04, 0x17, 0x58, 0x02, 0x00, 0x06 }, + /* 800MBps */ + { 0x06, 0x40, 0x03, 0x99, 0x64, 0x02, 0x00, 0x06 }, + /* 904MBps */ + { 0x07, 0x10, 0x03, 0x2f, 0x71, 0x00, 0x00, 0x06 }, + /* 960MBps */ + { 0x07, 0x80, 0x03, 0x00, 0x78, 0x02, 0x00, 0x06 }, + }, { /* lane 4 */ + /* 300MBps */ + { 0x04, 0xb0, 0x09, 0x99, 0x4b, 0x02, 0x01, 0x0c }, + /* 600MBps */ + { 0x09, 0x60, 0x04, 0xcc, 0x4b, 0x02, 0x00, 0x06 }, + /* 704MBps */ + { 0x0b, 0x00, 0x04, 0x17, 0x58, 0x02, 0x00, 0x06 }, + /* 800MBps */ + { 0x0c, 0x80, 0x03, 0x99, 0x64, 0x02, 0x00, 0x06 }, + /* 904MBps */ + { 0x0e, 0x20, 0x03, 0x2f, 0x71, 0x00, 0x00, 0x06 }, + /* 960MBps */ + { 0x0f, 0x00, 0x03, 0x00, 0x78, 0x00, 0x00, 0x06 }, + }, + }, + .hmax = { + { /* lane 2 */ + { 0x0e78, 0x1a80 }, /* 300MBps */ + { 0x0750, 0x0d54 }, /* 600MBps */ + { 0x0640, 0x0b60 }, /* 704MBps */ + { 0x0584, 0x0a06 }, /* 800MBps */ + { 0x04e8, 0x08e6 }, /* 904MBps */ + { 0x049e, 0x0860 }, /* 960MBps */ + }, { /* lane 4 */ + { 0x0860, 0x0e60 }, /* 300MBps */ + { 0x0444, 0x0744 }, /* 600MBps */ + { 0x03a8, 0x0636 }, /* 704MBps */ + { 0x033a, 0x057a }, /* 800MBps */ + { 0x02e2, 0x0514 }, /* 904MBps */ + { 0x02b6, 0x0514 }, /* 960MBps */ + }, + } +}; + +/* VGA sensor */ +static const struct mlx7502x_sensor_desc mlx75027 = { + .init_cfg = mlx7502x_75027_init_cfg, + .init_cfg_size = ARRAY_SIZE(mlx7502x_75027_init_cfg), + .link_freq_cfg = &mlx75027_link_freq_cfg, + .width = VGA_WIDTH, + .height = VGA_HEIGHT, +}; + +static const struct mlx7502x_regval_list mlx7502x_75026_init_cfg[] = { + { 0x477c, 0x0a }, { 0x477d, 0xd4 }, { 0x4964, 0x00 }, { 0x4965, 0xa0 }, + { 0x4967, 0xa1 }, { 0x4994, 0x00 }, { 0x4995, 0xa0 }, { 0x4997, 0xa1 }, + { 0x49c9, 0x78 }, { 0x49d3, 0x3c }, { 0x49d9, 0x76 }, { 0x49e3, 0x3f }, + { 0x49ec, 0x00 }, { 0x49ed, 0xa0 }, { 0x49ef, 0xa1 }, { 0x4a09, 0x3c }, + { 0x4a0f, 0x78 }, { 0x4a15, 0x3c }, { 0x4a1b, 0x76 }, { 0x4a21, 0x3f }, + { 0x4a2a, 0x00 }, { 0x4a2b, 0xa0 }, { 0x4a2d, 0xa1 }, { 0x4a2f, 0x78 }, + { 0x4a39, 0x3c }, { 0x4a5a, 0x00 }, { 0x4a5b, 0xa0 }, { 0x4a5d, 0xa1 }, + { 0x4a8a, 0x00 }, { 0x4a8b, 0xa0 }, { 0x4a8d, 0xa1 }, { 0x4afe, 0x00 }, + { 0x4aff, 0xa0 }, { 0x4b01, 0xa1 }, { 0x4b3e, 0x00 }, { 0x4b3f, 0xa0 }, + { 0x4b41, 0xa1 }, { 0x4b6a, 0x00 }, { 0x4b6b, 0xa0 }, { 0x4b6d, 0xa1 }, + { 0x4b96, 0x00 }, { 0x4b97, 0xa0 }, { 0x4b99, 0xa1 }, { 0x4bbf, 0x1a }, + { 0x4bd7, 0x1a }, { 0x4bdf, 0x1a }, { 0x4bfe, 0x00 }, { 0x4bff, 0xa0 }, + { 0x4c01, 0xa1 }, { 0x4c07, 0x1a }, { 0x4c11, 0x1a }, { 0x4c68, 0x00 }, + { 0x4c69, 0xa0 }, { 0x4c6b, 0xa1 }, { 0x4c7e, 0x00 }, { 0x4c7f, 0xa0 }, + { 0x4c81, 0xa1 }, { 0x4c8a, 0x01 }, { 0x4c8b, 0x35 }, { 0x4d02, 0x07 }, + { 0x4d03, 0xc9 }, { 0x4d08, 0x06 }, { 0x4d09, 0x9b }, { 0x4d0a, 0x07 }, + { 0x4d0b, 0xae }, { 0x4d0e, 0x07 }, { 0x4d0f, 0xc9 }, { 0x4d14, 0x06 }, + { 0x4d15, 0x98 }, { 0x4d16, 0x07 }, { 0x4d17, 0xb1 }, { 0x4d28, 0x06 }, + { 0x4d29, 0xa4 }, { 0x4d2b, 0xa9 }, { 0x4d2e, 0x07 }, { 0x4d2f, 0xc9 }, + { 0x4d3a, 0x07 }, { 0x4d3b, 0xc9 }, { 0x4d5a, 0x07 }, { 0x4d5b, 0xc9 }, + { 0x4d60, 0x06 }, { 0x4d61, 0x9b }, { 0x4d62, 0x07 }, { 0x4d63, 0xae }, + { 0x4d66, 0x07 }, { 0x4d67, 0xc9 }, { 0x4d6c, 0x06 }, { 0x4d6d, 0x98 }, + { 0x4d6e, 0x07 }, { 0x4d6f, 0xb1 }, { 0x4d83, 0xa9 }, { 0x4d88, 0x06 }, + { 0x4d89, 0xa4 }, { 0x4d8a, 0x07 }, { 0x4d8b, 0xae }, { 0x4d8c, 0x1f }, + { 0x4d8d, 0xff }, { 0x4d8e, 0x1f }, { 0x4d8f, 0xff }, { 0x4d90, 0x06 }, + { 0x4d91, 0xa4 }, { 0x4d92, 0x07 }, { 0x4d93, 0xae }, { 0x4d94, 0x1f }, + { 0x4d95, 0xff }, { 0x4d96, 0x1f }, { 0x4d97, 0xff }, +}; + +static const struct mlx7502x_link_freq_list mlx75026_link_freq_cfg = { + .link_freq = { + 300000000, + 600000000, + 704000000, + 800000000, + 904000000, + 960000000 + }, + .addr = { + 0x100c, 0x100d, 0x1016, 0x1017, 0x1045, 0x1047, 0x1060, 0x1071 + }, + .data = { + { /* lane 2 */ + /* 300MBps */ + { 0x02, 0x58, 0x09, 0x99, 0x4b, 0x02, 0x01, 0x0c }, + /* 600MBps */ + { 0x04, 0xb0, 0x04, 0xcc, 0x4b, 0x02, 0x00, 0x06 }, + /* 704MBps */ + { 0x05, 0x80, 0x04, 0x17, 0x58, 0x02, 0x00, 0x06 }, + /* 800MBps */ + { 0x06, 0x40, 0x03, 0x99, 0x64, 0x02, 0x00, 0x06 }, + /* 904MBps */ + { 0x07, 0x10, 0x03, 0x2f, 0x71, 0x00, 0x00, 0x06 }, + /* 960MBps */ + { 0x07, 0x80, 0x03, 0x00, 0x78, 0x02, 0x00, 0x06 }, + }, { /* lane 4 */ + /* 300MBps */ + { 0x04, 0xb0, 0x09, 0x99, 0x4b, 0x02, 0x01, 0x0c }, + /* 600MBps */ + { 0x09, 0x60, 0x04, 0xcc, 0x4b, 0x02, 0x00, 0x06 }, + /* 704MBps */ + { 0x0b, 0x00, 0x04, 0x17, 0x58, 0x02, 0x00, 0x06 }, + /* 800MBps */ + { 0x0c, 0x80, 0x03, 0x99, 0x64, 0x02, 0x00, 0x06 }, + /* 904MBps */ + { 0x0e, 0x20, 0x03, 0x2f, 0x71, 0x00, 0x00, 0x06 }, + /* 960MBps */ + { 0x0f, 0x00, 0x03, 0x00, 0x78, 0x00, 0x00, 0x06 }, + }, + }, + .hmax = { + { /* lane 2 */ + { 0x0878, 0x0e80 }, /* 300MBps */ + { 0x0450, 0x0754 }, /* 600MBps */ + { 0x03b2, 0x0644 }, /* 704MBps */ + { 0x0344, 0x0586 }, /* 800MBps */ + { 0x02ea, 0x0514 }, /* 904MBps */ + { 0x02be, 0x0514 }, /* 960MBps */ + }, { /* lane 4 */ + { 0x0560, 0x0860 }, /* 300MBps */ + { 0x02c4, 0x0444 }, /* 600MBps */ + { 0x02b6, 0x03a8 }, /* 704MBps */ + { 0x02b6, 0x033a }, /* 800MBps */ + { 0x02b6, 0x02e2 }, /* 904MBps */ + { 0x02b6, 0x02b6 }, /* 960MBps */ + }, + } +}; + +/* QVGA sensor */ +static const struct mlx7502x_sensor_desc mlx75026 = { + .init_cfg = mlx7502x_75026_init_cfg, + .init_cfg_size = ARRAY_SIZE(mlx7502x_75026_init_cfg), + .link_freq_cfg = &mlx75026_link_freq_cfg, + .width = QVGA_WIDTH, + .height = QVGA_HEIGHT, +}; + +static const struct mlx7502x_binning_mode binning_mode[] = { + { .reg_value = 0, .ratio = 1, .width_align = 2, .height_align = 1, + .width_min = 8, .height_min = 2 }, + { .reg_value = 1, .ratio = 2, .width_align = 3, .height_align = 1, + .width_min = 16, .height_min = 2 }, + { .reg_value = 2, .ratio = 4, .width_align = 4, .height_align = 2, + .width_min = 32, .height_min = 4 }, + { .reg_value = 3, .ratio = 8, .width_align = 5, .height_align = 3, + .width_min = 64, .height_min = 8 }, +}; + +static const struct mlx7502x_fmod_list mlx7502x_fmod_cfg[] = { + { .fmod = 100000000, .divselpre = 0, .divsel = 0, }, + { .fmod = 75000000, .divselpre = 0, .divsel = 0, }, + { .fmod = 74000000, .divselpre = 1, .divsel = 0, }, + { .fmod = 51000000, .divselpre = 1, .divsel = 0, }, + { .fmod = 50000000, .divselpre = 0, .divsel = 1, }, + { .fmod = 38000000, .divselpre = 0, .divsel = 1, }, + { .fmod = 37000000, .divselpre = 1, .divsel = 1, }, + { .fmod = 21000000, .divselpre = 1, .divsel = 1, }, + { .fmod = 2000000, .divselpre = 0, .divsel = 2, }, + { .fmod = 1000000, .divselpre = 0, .divsel = 2, }, + { .fmod = 1000000, .divselpre = 1, .divsel = 2, }, + { .fmod = 1000000, .divselpre = 1, .divsel = 2, }, + { .fmod = 900000, .divselpre = 2, .divsel = 2, }, + { .fmod = 500000, .divselpre = 2, .divsel = 2, }, + { .fmod = 400000, .divselpre = 3, .divsel = 2, }, +}; + +static const struct mlx7502x_regval_list mlx7502x_trigger_cfg[] = { + { 0x2020, 0x01 }, { 0x2f05, 0x01 }, { 0x2f06, 0x09 }, + { 0x2f07, 0x7a }, { 0x3071, 0x00 }, +}; + +static const struct mlx7502x_regval_list mlx7502x_ext_trigger_cfg[] = { + { 0x2020, 0x00 }, { 0x2f05, 0x07 }, { 0x2f06, 0x00 }, + { 0x2f07, 0x00 }, { 0x3071, 0x03 }, +}; + +static const char * const mlx7502x_ctrl_output[] = { + [V4L2_MLX7502X_OUTPUT_MODE_A_MINUS_B] = "A minus B", + [V4L2_MLX7502X_OUTPUT_MODE_A_PLUS_B] = "A plus B", + [V4L2_MLX7502X_OUTPUT_MODE_A] = "Raw A", + [V4L2_MLX7502X_OUTPUT_MODE_B] = "Raw B", + [V4L2_MLX7502X_OUTPUT_MODE_A_AND_B] = "Raw A and Raw B", +}; + +static const struct mlx7502x_output_mode mlx7502x_output_mode_cfg[] = { + [V4L2_MLX7502X_OUTPUT_MODE_A_MINUS_B] = { + .hmax_index = 0, .width_mult = 1 + }, + [V4L2_MLX7502X_OUTPUT_MODE_A_PLUS_B] = { + .hmax_index = 0, .width_mult = 1 + }, + [V4L2_MLX7502X_OUTPUT_MODE_A] = { + .hmax_index = 0, .width_mult = 1 + }, + [V4L2_MLX7502X_OUTPUT_MODE_B] = { + .hmax_index = 0, .width_mult = 1 + }, + [V4L2_MLX7502X_OUTPUT_MODE_A_AND_B] = { + .hmax_index = 1, .width_mult = 2 + } +}; + +static inline struct mlx7502x *to_mlx7502x(struct v4l2_subdev *sd) +{ + return container_of(sd, struct mlx7502x, sd); +} + +static int mlx7502x_read(struct v4l2_subdev *sd, u16 reg, u8 *val, int val_size) +{ + int ret; + unsigned char data_w[2]; + struct i2c_client *client = v4l2_get_subdevdata(sd); + + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = 2, + .buf = data_w, + }, { + .addr = client->addr, + .flags = I2C_M_RD, + .len = val_size, + .buf = val, + } + }; + + /* write reg address into first msg */ + put_unaligned_be16(reg, data_w); + + /* Using transfer allows skip STOP between messages + * so we have repeated Start here + */ + ret = i2c_transfer(client->adapter, msg, 2); + + return ret != 2 ? -EIO : 0; +} + +static int mlx7502x_write(struct v4l2_subdev *sd, u8 *data, u32 data_size, + int *err) +{ + int ret; + struct i2c_client *client = v4l2_get_subdevdata(sd); + + if (err && *err) + return *err; + + dev_dbg(&client->dev, "%*ph\n", data_size, data); + + ret = i2c_master_send(client, data, data_size); + if (ret < 0) { + dev_dbg(&client->dev, "%s: i2c write error, reg: 0x%x%x\n", + __func__, data[0], data[1]); + + return ret; + } + + return ret != data_size ? -EIO : 0; +} + +static int mlx7502x_write8(struct v4l2_subdev *sd, u16 reg, u8 val, int *err) +{ + unsigned char data[3]; + + put_unaligned_be16(reg, data); + data[2] = val; + + return mlx7502x_write(sd, data, 3, err); +} + +static int mlx7502x_write16(struct v4l2_subdev *sd, u16 reg, u16 val, int *err) +{ + unsigned char data[4]; + + put_unaligned_be16(reg, data); + put_unaligned_be16(val, data + 2); + + return mlx7502x_write(sd, data, 4, err); +} + +static int mlx7502x_write24(struct v4l2_subdev *sd, u16 reg, u32 val, int *err) +{ + unsigned char data[5]; + + put_unaligned_be16(reg, data); + put_unaligned_be24(val, data + 2); + + return mlx7502x_write(sd, data, 5, err); +} + +static int mlx7502x_write32(struct v4l2_subdev *sd, u16 reg, u32 val, int *err) +{ + unsigned char data[6]; + + put_unaligned_be16(reg, data); + put_unaligned_be32(val, data + 2); + + return mlx7502x_write(sd, data, 6, err); +} + +static int mlx7502x_write_regval(struct v4l2_subdev *sd, + const struct mlx7502x_regval_list *regs, + int array_size) +{ + int i, ret; + + for (i = 0; i < array_size; i++) { + ret = mlx7502x_write8(sd, regs[i].addr, regs[i].data, NULL); + if (ret < 0) + return ret; + } + + return 0; +} + +static int mlx7502x_write_array(struct v4l2_subdev *sd, const u16 *reg, + const u8 *data, int size, int *err) +{ + int i, ret; + + for (i = 0; i < size; i++) { + ret = mlx7502x_write8(sd, reg[i], data[i], err); + if (ret < 0) + return ret; + } + + return 0; +} + +/* + * ***************************************************************************** + * PM + * ***************************************************************************** + */ +static int mlx7502x_power_off(struct mlx7502x *sensor) +{ + gpiod_set_value_cansleep(sensor->reset, 0); + + clk_disable_unprepare(sensor->xclk); + + regulator_bulk_disable(MLX7502X_NUM_SUPPLIES, sensor->supplies); + + dev_dbg(sensor->dev, "power off\n"); + + return 0; +} + +static int __maybe_unused mlx7502x_runtime_resume(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct mlx7502x *sensor = to_mlx7502x(sd); + int ret; + + gpiod_set_value_cansleep(sensor->reset, 0); + + ret = regulator_bulk_enable(MLX7502X_NUM_SUPPLIES, sensor->supplies); + if (ret) { + dev_err(sensor->dev, "failed to enable supply: %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(sensor->xclk); + if (ret) { + dev_err(sensor->dev, "failed to enable external clock: %d\n", + ret); + goto fail_clk; + } + + gpiod_set_value_cansleep(sensor->reset, 1); + msleep(MLX7502X_RESET_DELAY_MS); + + dev_dbg(sensor->dev, "power on\n"); + + ret = mlx7502x_write_regval(sd, mlx7502x_common_init_cfg, + ARRAY_SIZE(mlx7502x_common_init_cfg)); + if (ret < 0) { + dev_err(sensor->dev, "failed to write init_cfg\n"); + goto fail_clk; + } + + ret = mlx7502x_write_regval(sd, sensor->cur_desc->init_cfg, + sensor->cur_desc->init_cfg_size); + if (ret < 0) { + dev_err(sensor->dev, "failed to write sensor specific init_cfg\n"); + goto fail_clk; + } + + return 0; + +fail_clk: + regulator_bulk_disable(MLX7502X_NUM_SUPPLIES, sensor->supplies); + return ret; +} + +static int __maybe_unused mlx7502x_runtime_suspend(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct mlx7502x *sensor = to_mlx7502x(sd); + + mlx7502x_power_off(sensor); + + return 0; +} + +/* + * ***************************************************************************** + * Subdev operations + * ***************************************************************************** + */ +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int mlx7502x_get_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + u8 val[4]; + int ret; + + /* v4l2-dbg set it to 0 */ + if (reg->size == 0) + reg->size = 1; + + ret = mlx7502x_read(sd, reg->reg & 0xffff, val, reg->size); + if (ret < 0) + return ret; + + if (reg->size == 1) + reg->val = val[0]; + else if (reg->size == 2) + reg->val = get_unaligned_be16(val); + else if (reg->size == 3) + reg->val = get_unaligned_be24(val); + else if (reg->size == 4) + reg->val = get_unaligned_be32(val); + else + return -EINVAL; + + return 0; +} + +static int mlx7502x_set_register(struct v4l2_subdev *sd, + const struct v4l2_dbg_register *reg) +{ + if (reg->size <= 1) + return mlx7502x_write8(sd, reg->reg & 0xffff, reg->val, NULL); + else if (reg->size == 2) + return mlx7502x_write16(sd, reg->reg & 0xffff, reg->val, NULL); + else if (reg->size == 3) + return mlx7502x_write24(sd, reg->reg & 0xffff, reg->val, NULL); + else if (reg->size == 4) + return mlx7502x_write32(sd, reg->reg & 0xffff, reg->val, NULL); + + return -EINVAL; +} +#endif + +/* from us into sensor ticks */ +static unsigned int mlx7502x_from_us(struct mlx7502x *sensor, u32 us) +{ + return DIV_ROUND_CLOSEST(us * MLX7502X_CLK_RATE_MHZ, sensor->hmax); +} + +static unsigned int mlx7502x_to_us(struct mlx7502x *sensor, u32 reg) +{ + return DIV_ROUND_CLOSEST(reg * sensor->hmax, MLX7502X_CLK_RATE_MHZ); +} + +static int mlx7502x_set_link_freq(struct mlx7502x *sensor) +{ + struct v4l2_subdev *sd = &sensor->sd; + const struct mlx7502x_link_freq_list *lfc; + int link_freq = sensor->link_freq->val; + struct v4l2_mbus_config_mipi_csi2 *bus = &sensor->ep.bus.mipi_csi2; + u8 cont_clock, lane_n = bus->num_data_lanes; + u32 pretime; + int ret; + + /* lane */ + ret = mlx7502x_write8(sd, MLX7502X_DATA_LANE_CONFIG_REG, + lane_n - 1, NULL); + + /* link freq */ + lfc = sensor->cur_desc->link_freq_cfg; + ret = mlx7502x_write_array(sd, lfc->addr, + lfc->data[lane_n >> 2][link_freq], + MLX7502X_LINK_FREQ_REG_N, &ret); + + /* clock continuous mode if MIPI receiver requires it */ + cont_clock = bus->flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK ? 1u : 0u; + ret = mlx7502x_write8(sd, MLX7502X_CONTINUOUS_REG, cont_clock, &ret); + + ret = mlx7502x_write16(sd, MLX7502X_HMAX_REG, sensor->hmax, &ret); + + /* timings which depends on hmax and mipi config */ + ret = mlx7502x_write8(sd, MLX7502X_PLLSETUP_REG, + mlx7502x_from_us(sensor, MLX7502X_PLLSETUP_US) + + MLX7502X_PLLSETUP_TICKS, &ret); + + pretime = mlx7502x_from_us(sensor, MLX7502X_PRETIME_US); + ret = mlx7502x_write16(sd, MLX7502X_PRETIME_REG, pretime, &ret); + + return mlx7502x_write24(sd, MLX7502X_RANDNM0_REG, + pretime * sensor->hmax - 1070 - 2098, &ret); +} + +static int mlx7502x_update_output_format(struct mlx7502x *sensor, + struct v4l2_subdev_state *state) +{ + struct v4l2_subdev *sd = &sensor->sd; + struct v4l2_rect *crop = v4l2_subdev_state_get_crop(state, 0); + int ret; + + ret = mlx7502x_write16(sd, MLX7502X_COLUMN_START_REG, + crop->left + 1u, NULL); + ret = mlx7502x_write16(sd, MLX7502X_COLUMN_LEN_REG, + crop->width, &ret); + ret = mlx7502x_write16(sd, MLX7502X_ROW_START_REG, + MLX7502X_ROW_START(crop->top), &ret); + ret = mlx7502x_write16(sd, MLX7502X_ROW_END_REG, + MLX7502X_ROW_END(crop->top, crop->height), &ret); + ret = mlx7502x_write8(sd, MLX7502X_BINNING_REG, + sensor->binning_mode->reg_value, &ret); + return mlx7502x_write8(sd, MLX7502X_OUTPUT_MODE_REG, + sensor->output_mode->val, &ret); +} + +static int __mlx7502x_set_frame_interval(struct mlx7502x *sensor, + struct v4l2_subdev_state *state, + struct v4l2_fract *fi, uint32_t which, + u32 phase_n, u16 *tint) +{ + struct v4l2_fract *interval; + struct v4l2_rect *crop; + u32 req_fi_us, min_fi_us, readout_ticks, tint_sum = 0, pllsetup_us; + int ret, i, fi_register = 0; + + if (sensor->trigger_mode->val == V4L2_TRIGGER_MODE_CONTINUOUS) { + interval = v4l2_subdev_state_get_interval(state, 0); + if (!fi) + fi = interval; + + if (fi->denominator == 0 || fi->numerator == 0) { + fi->numerator = 1; + fi->denominator = MLX7502X_DEFAULT_FRAME_RATE; + } + + crop = v4l2_subdev_state_get_crop(state, 0); + + readout_ticks = MLX7502X_ROW_END(crop->top, crop->height) + - MLX7502X_ROW_START(crop->top) + 1; + + for (i = 0; i < phase_n; i++) + tint_sum += tint[i]; + + pllsetup_us = MLX7502X_PLLSETUP_US + + mlx7502x_to_us(sensor, MLX7502X_PLLSETUP_TICKS); + + min_fi_us = pllsetup_us + tint_sum + + (mlx7502x_to_us(sensor, + readout_ticks + + MLX7502X_FRAME_ADD_TICKS) + + MLX7502X_PRETIME_US) + * phase_n; + + req_fi_us = MICRO * fi->numerator / fi->denominator; + + dev_dbg(sensor->dev, + "frame interval: min = %dus, requested = %dus\n", + min_fi_us, req_fi_us); + + if (req_fi_us < min_fi_us) { + req_fi_us = min_fi_us; + fi->numerator = 1; + fi->denominator = MICRO / req_fi_us; + } + + if (fi != interval) + *interval = *fi; + + fi_register = mlx7502x_from_us(sensor, req_fi_us - pllsetup_us); + } + + if (which != V4L2_SUBDEV_FORMAT_ACTIVE) + return 0; + + if (!pm_runtime_get_if_in_use(sensor->dev)) + return 0; + + ret = mlx7502x_write32(&sensor->sd, MLX7502X_FRAME_TIME_REG, + fi_register, NULL); + + pm_runtime_put_autosuspend(sensor->dev); + + return ret; +} + +static int mlx7502x_s_stream(struct v4l2_subdev *sd, int on) +{ + struct mlx7502x *sensor = to_mlx7502x(sd); + struct v4l2_subdev_state *state; + int ret = 0; + + state = v4l2_subdev_lock_and_get_active_state(sd); + + if (on && !sensor->streaming) { + ret = pm_runtime_resume_and_get(sensor->dev); + if (ret < 0) { + v4l2_subdev_unlock_state(state); + return ret; + } + + ret = __v4l2_ctrl_handler_setup(sd->ctrl_handler); + if (ret < 0) + goto error_stream; + /* + * the registers below depends on hmax, + * which is configured in controls + */ + ret = mlx7502x_set_link_freq(sensor); + if (ret < 0) + goto error_stream; + ret = mlx7502x_update_output_format(sensor, state); + if (ret < 0) + goto error_stream; + + ret = mlx7502x_write8(sd, MLX7502X_STREAM_EN_REG, 1u, NULL); + if (ret < 0) + goto error_stream; + + sensor->streaming = 1u; + dev_dbg(sensor->dev, "stream enabled\n"); + + /* we need to wait to stabilize the system after streaming on */ + msleep(MLX7502X_STREAMING_DELAY_MS); + } else if (!on && sensor->streaming) { + sensor->streaming = 0u; + ret = mlx7502x_write8(sd, MLX7502X_STREAM_EN_REG, 0u, NULL); + /* we need to wait in case last buffer is sending */ + msleep(MLX7502X_STREAMING_DELAY_MS); + dev_dbg(sensor->dev, "stream disabled\n"); + + pm_runtime_mark_last_busy(sensor->dev); + pm_runtime_put_autosuspend(sensor->dev); + } + + __v4l2_ctrl_grab(sensor->trigger_mode, on); + + v4l2_subdev_unlock_state(state); + return ret; + +error_stream: + dev_err(sensor->dev, "failed to enable stream(%d)\n", ret); + pm_runtime_put(sensor->dev); + v4l2_subdev_unlock_state(state); + return ret; +} + +static int mlx7502x_set_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_frame_interval *fi) +{ + struct mlx7502x *sensor = to_mlx7502x(sd); + + if (sensor->trigger_mode->val != V4L2_TRIGGER_MODE_CONTINUOUS) + return -EBUSY; + + return __mlx7502x_set_frame_interval(sensor, state, + &fi->interval, + fi->which, + sensor->phase_seq->elems, + sensor->tint->p_cur.p_u16); +} + +static int mlx7502x_get_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_frame_interval *fi) +{ + struct mlx7502x *sensor = to_mlx7502x(sd); + + if (sensor->trigger_mode->val != V4L2_TRIGGER_MODE_CONTINUOUS) + return -EBUSY; + + return v4l2_subdev_get_frame_interval(sd, state, fi); +} + +static int mlx7502x_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index > 0) + return -EINVAL; + + code->code = MEDIA_BUS_FMT_Y12_1X12; + + return 0; +} + +static int mlx7502x_set_format(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_format *fmt) +{ + struct mlx7502x *sensor = to_mlx7502x(sd); + struct v4l2_rect *compose = v4l2_subdev_state_get_compose(state, 0); + int output_mode = sensor->output_mode->val; + struct v4l2_mbus_framefmt *format; + int width_mult; + + format = v4l2_subdev_state_get_format(state, 0); + + width_mult = mlx7502x_output_mode_cfg[output_mode].width_mult; + + memset(format, 0, sizeof(*format)); + format->code = MEDIA_BUS_FMT_Y12_1X12; + format->width = width_mult * compose->width; + format->height = compose->height; + format->field = V4L2_FIELD_NONE; + format->colorspace = V4L2_COLORSPACE_RAW; + format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + format->quantization = V4L2_QUANTIZATION_FULL_RANGE; + format->xfer_func = V4L2_XFER_FUNC_NONE; + + if (fmt) + fmt->format = *format; + + return 0; +} + +static const struct mlx7502x_binning_mode * +mlx7502x_find_binning_mode(struct v4l2_rect *crop, struct v4l2_rect *compose) +{ + int i; + const struct mlx7502x_binning_mode *bin_mode; + u8 ratio = compose->width == 0u ? 1u : crop->width / compose->width; + + for (i = 0; i < ARRAY_SIZE(binning_mode); i++) { + bin_mode = &binning_mode[i]; + + if (bin_mode->ratio == ratio) + break; + } + + return bin_mode; +} + +static void mlx7502x_set_crop(struct mlx7502x *sensor, + struct v4l2_subdev_state *state, + struct v4l2_subdev_selection *sel, + struct v4l2_rect *dst_crop, + struct v4l2_rect *dst_compose, + const struct mlx7502x_binning_mode *bin_mode) +{ + u32 w, h; + + /* + * cropping will always be in native size, + * even if binning was applied + */ + w = sensor->cur_desc->width; + h = sensor->cur_desc->height; + + v4l_bound_align_image(&sel->r.width, bin_mode->width_min, w, + bin_mode->width_align, + &sel->r.height, bin_mode->height_min, h, + bin_mode->height_align, 0); + + v4l_bound_align_image(&sel->r.left, MLX7502X_LEFT_MIN, w - sel->r.width, + MLX7502X_LEFT_ALIGN, + &sel->r.top, MLX7502X_TOP_MIN, h - sel->r.height, + MLX7502X_TOP_ALIGN, 0); + /* fill active or try */ + *dst_crop = sel->r; + /* update binning w/h, as actual crop size could changed */ + dst_compose->top = 0; + dst_compose->left = 0; + dst_compose->width = dst_crop->width / bin_mode->ratio; + dst_compose->height = dst_crop->height / bin_mode->ratio; + + /* update frame interval, but don't write into sensor yet */ + if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) + __mlx7502x_set_frame_interval(sensor, state, + NULL, + V4L2_SUBDEV_FORMAT_TRY, + sensor->phase_seq->elems, + sensor->tint->p_cur.p_u16); +} + +/* + * Binning is applied after cropping inside the sensor + */ +static void mlx7502x_set_compose(struct mlx7502x *sensor, + struct v4l2_subdev_state *state, + struct v4l2_subdev_selection *sel, + struct v4l2_rect *dst_crop, + struct v4l2_rect *dst_compose) +{ + const struct mlx7502x_binning_mode *bin_mode; + u32 w, h, i, bin_w, bin_h; + + w = dst_crop->width; + h = dst_crop->height; + + /* select the best binning */ + for (i = 0; i < ARRAY_SIZE(binning_mode); i++) { + bin_mode = &binning_mode[i]; + + if (sel->flags & V4L2_SEL_FLAG_LE) { + bin_w = w / bin_mode->ratio; + bin_h = h / bin_mode->ratio; + } else {/* for GE and KEEP choose lower bin_w/h */ + bin_w = w / bin_mode[1].ratio + 1; + bin_h = h / bin_mode[1].ratio + 1; + } + + if (sel->r.width >= bin_w && sel->r.height >= bin_h) + break; + } + + /* save new binning config */ + if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) + sensor->binning_mode = bin_mode; + + /* update crop step and min, based on new binning */ + sel->r = *dst_crop; + mlx7502x_set_crop(sensor, state, sel, dst_crop, dst_compose, bin_mode); + + /* resulted format after applying new binning */ + sel->r = *dst_compose; +} + +static int mlx7502x_set_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_selection *sel) +{ + struct mlx7502x *sensor = to_mlx7502x(sd); + struct v4l2_rect *crop, *compose; + const struct mlx7502x_binning_mode *bin_mode; + int ret = 0; + + crop = v4l2_subdev_state_get_crop(state, 0); + compose = v4l2_subdev_state_get_compose(state, 0); + bin_mode = mlx7502x_find_binning_mode(crop, compose); + + if (sel->target == V4L2_SEL_TGT_CROP) + mlx7502x_set_crop(sensor, state, sel, crop, compose, bin_mode); + else if (sel->target == V4L2_SEL_TGT_COMPOSE) + /* actually this is binning */ + mlx7502x_set_compose(sensor, state, sel, crop, compose); + else + ret = -EINVAL; + + /* update format state */ + if (ret == 0) + mlx7502x_set_format(sd, state, NULL); + + return ret; +} + +static int mlx7502x_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_selection *sel) +{ + struct mlx7502x *sensor = to_mlx7502x(sd); + struct v4l2_rect *crop, *compose; + int ret = 0; + + crop = v4l2_subdev_state_get_crop(state, 0); + compose = v4l2_subdev_state_get_compose(state, 0); + + switch (sel->target) { + case V4L2_SEL_TGT_CROP: + sel->r = *crop; + break; + case V4L2_SEL_TGT_CROP_DEFAULT: + case V4L2_SEL_TGT_CROP_BOUNDS: + case V4L2_SEL_TGT_NATIVE_SIZE: + sel->r.top = 0; + sel->r.left = 0; + sel->r.width = sensor->cur_desc->width; + sel->r.height = sensor->cur_desc->height; + break; + case V4L2_SEL_TGT_COMPOSE: + sel->r = *compose; + break; + case V4L2_SEL_TGT_COMPOSE_BOUNDS: + sel->r.top = 0; + sel->r.left = 0; + sel->r.width = crop->width; + sel->r.height = crop->height; + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int mlx7502x_init_state(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) +{ + struct mlx7502x *sensor = to_mlx7502x(sd); + struct v4l2_fract *interval; + + struct v4l2_subdev_selection sel = { + .target = V4L2_SEL_TGT_CROP, + .r.width = sensor->cur_desc->width, + .r.height = sensor->cur_desc->height, + }; + struct v4l2_fract fi = { + .numerator = 1, + .denominator = MLX7502X_DEFAULT_FRAME_RATE, + }; + + // it will also update compose and format state + mlx7502x_set_selection(sd, state, &sel); + + interval = v4l2_subdev_state_get_interval(state, 0); + *interval = fi; + + return 0; +} + +static const struct v4l2_subdev_core_ops mlx7502x_subdev_core_ops = { + .subscribe_event = v4l2_ctrl_subdev_subscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = mlx7502x_get_register, + .s_register = mlx7502x_set_register, +#endif +}; + +static const struct v4l2_subdev_video_ops mlx7502x_subdev_video_ops = { + .s_stream = mlx7502x_s_stream, +}; + +static const struct v4l2_subdev_pad_ops mlx7502x_subdev_pad_ops = { + .enum_mbus_code = mlx7502x_enum_mbus_code, + .set_fmt = mlx7502x_set_format, + .get_fmt = v4l2_subdev_get_fmt, + .set_selection = mlx7502x_set_selection, + .get_selection = mlx7502x_get_selection, + .get_frame_interval = mlx7502x_get_frame_interval, + .set_frame_interval = mlx7502x_set_frame_interval, +}; + +static const struct v4l2_subdev_ops mlx7502x_subdev_ops = { + .core = &mlx7502x_subdev_core_ops, + .video = &mlx7502x_subdev_video_ops, + .pad = &mlx7502x_subdev_pad_ops, +}; + +static const struct v4l2_subdev_internal_ops mlx7502x_internal_ops = { + .init_state = mlx7502x_init_state, +}; + +/* + * ***************************************************************************** + * Controls + * ***************************************************************************** + */ +static __always_inline u8 mlx7502x_phase_to_reg(u16 phase) +{ + /* Note: + * Sensor is working in mode when: + * MIX is a referance, + * and illumination is shifted + * To compensate it, we need to add 180 degrees + */ + if (phase != 0 && phase != 180) + phase = (phase + 180) % 360; + + return phase / 45; +} + +static int mlx7502x_set_phase_seq(struct mlx7502x *sensor, + struct v4l2_subdev_state *state, + struct v4l2_ctrl *ctrl) +{ + int ret; + int i, offset; + u16 *p_v; + u8 val; + u8 *data; + /* address + number of phases(1 phases - 1 nibble) */ + size_t data_size = 2 + DIV_ROUND_CLOSEST(ctrl->new_elems, 2); + + data = kmalloc(data_size, GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* the address */ + put_unaligned_be16(MLX7502X_PX_PHASE_SHIFT_REG, data); + + /* data itself */ + offset = 2; + p_v = ctrl->p_new.p_u16; + for (i = 0; i < (ctrl->new_elems - 1); i += 2) { + val = FIELD_PREP(MLX7502X_NIBLE_LOW_MASK, + mlx7502x_phase_to_reg(p_v[i])); + + val |= FIELD_PREP(MLX7502X_NIBLE_HIGH_MASK, + mlx7502x_phase_to_reg(p_v[i + 1])); + + data[offset++] = val; + } + + /* last odd field if any */ + if (i < ctrl->new_elems) + data[offset] = FIELD_PREP(MLX7502X_NIBLE_LOW_MASK, + mlx7502x_phase_to_reg(p_v[i])); + + /* set phase sequence */ + ret = mlx7502x_write(&sensor->sd, data, data_size, NULL); + + /* set number of phases */ + ret = mlx7502x_write8(&sensor->sd, MLX7502X_PHASE_COUNT_REG, + ctrl->new_elems, &ret); + kfree(data); + + if (!ret) + ret = __mlx7502x_set_frame_interval(sensor, state, + NULL, + V4L2_SUBDEV_FORMAT_ACTIVE, + sensor->phase_seq->new_elems, + sensor->tint->p_cur.p_u16); + return ret; +} + +/* comparator for bsearch func */ +static int mlx7502x_fmod_cmp(const void *key, const void *elt) +{ + int ret = 1; /* lower then lowest */ + u32 val = *((u32 *)key); + /* need prev elt for range checking, so key requires to be >= 4 */ + struct mlx7502x_fmod_list *el = (struct mlx7502x_fmod_list *)elt - 1; + u32 high = el[0].fmod; + u32 low = el[1].fmod; + + if (val > high) /* more then the highest, move to lower index */ + ret = -1; + else if (val >= low) /* we are in a range */ + ret = 0; + + return ret; +} + +static int mlx7502x_set_fmod(struct mlx7502x *sensor, u32 fmod) +{ + int ret; + u16 fmod_reg; + u8 pll_res_reg; + struct v4l2_subdev *sd = &sensor->sd; + struct mlx7502x_fmod_list *fc; + + fc = bsearch(&fmod, + mlx7502x_fmod_cfg, + ARRAY_SIZE(mlx7502x_fmod_cfg), + sizeof(struct mlx7502x_fmod_list), + mlx7502x_fmod_cmp); + + ret = mlx7502x_write8(sd, MLX7502X_DIVSELPRE_REG, fc->divselpre, NULL); + ret = mlx7502x_write8(sd, MLX7502X_DIVSEL_REG, fc->divsel, &ret); + + fmod_reg = (fmod / 1000000u) << (fc->divselpre + fc->divsel); + ret = mlx7502x_write16(sd, MLX7502X_FMOD_REG, fmod_reg, &ret); + + pll_res_reg = fmod_reg < MLX7502X_PLL_RES_THR ? 2 : 0; + return mlx7502x_write8(sd, MLX7502X_PLL_RES_REG, pll_res_reg, &ret); +} + +static int mlx7502x_set_tint(struct mlx7502x *sensor, + struct v4l2_subdev_state *state, + struct v4l2_ctrl *ctrl) +{ + int i, offset, ret = 0; + u16 *p_v; + u32 tint_reg; + u8 *data; + /* address + number of phases(1 phases - 4bytes) */ + size_t data_size = 2 + ctrl->new_elems * 4; + + data = kmalloc(data_size, GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* the address */ + put_unaligned_be16(MLX7502X_TINT0_REG, data); + + /* data itself */ + p_v = ctrl->p_new.p_u16; + for (i = 0; i < ctrl->new_elems; i++) { + offset = 2 + i * 4; + tint_reg = mlx7502x_from_us(sensor, p_v[i]) * sensor->hmax; + put_unaligned_be32(tint_reg, data + offset); + } + + ret = mlx7502x_write(&sensor->sd, data, data_size, NULL); + kfree(data); + + if (!ret) + ret = __mlx7502x_set_frame_interval(sensor, state, + NULL, + V4L2_SUBDEV_FORMAT_ACTIVE, + sensor->phase_seq->elems, + sensor->tint->p_new.p_u16); + return ret; +} + +static int mlx7502x_update_hmax(struct mlx7502x *sensor, + int mipi_speed_ind, + int output_mode) +{ + const struct mlx7502x_link_freq_list *lfc; + int hmax_index = mlx7502x_output_mode_cfg[output_mode].hmax_index; + u8 lane_n = sensor->ep.bus.mipi_csi2.num_data_lanes; + u32 tint_step; + + lfc = sensor->cur_desc->link_freq_cfg; + sensor->hmax = lfc->hmax[lane_n >> 2][mipi_speed_ind][hmax_index]; + + tint_step = mlx7502x_to_us(sensor, 1); + return __v4l2_ctrl_modify_range(sensor->tint, + tint_step, + sensor->tint->maximum, + tint_step, + sensor->tint->default_value); +} + +static int mlx7502x_set_trigger_mode(struct mlx7502x *sensor, + enum v4l2_trigger_mode mode) +{ + int ret; + struct v4l2_subdev *sd = &sensor->sd; + bool trigger_grab = false; + + switch (mode) { + case V4L2_TRIGGER_MODE_CONTINUOUS: + ret = mlx7502x_write_regval(sd, mlx7502x_trigger_cfg, + ARRAY_SIZE(mlx7502x_trigger_cfg)); + ret = mlx7502x_write8(sd, MLX7502X_SW_TRIGGER_REG, + MLX7502X_SW_TRIGGER_CONT, &ret); + trigger_grab = true; + break; + case V4L2_TRIGGER_MODE_INTERNAL: + ret = mlx7502x_write_regval(sd, mlx7502x_trigger_cfg, + ARRAY_SIZE(mlx7502x_trigger_cfg)); + ret = mlx7502x_write8(sd, MLX7502X_SW_TRIGGER_REG, + MLX7502X_SW_TRIGGER_DEFAULT, &ret); + trigger_grab = false; + break; + case V4L2_TRIGGER_MODE_EXTERNAL: + ret = mlx7502x_write_regval(sd, mlx7502x_ext_trigger_cfg, + ARRAY_SIZE(mlx7502x_ext_trigger_cfg)); + ret = mlx7502x_write8(sd, MLX7502X_SW_TRIGGER_REG, + MLX7502X_SW_TRIGGER_DEFAULT, &ret); + trigger_grab = true; + break; + default: + /* should not be there */ + ret = -EINVAL; + break; + } + + if (ret == 0) + __v4l2_ctrl_grab(sensor->trigger, trigger_grab); + + return ret; +} + +static int mlx7502x_hold(struct mlx7502x *sensor, u32 id, u8 hold) +{ + int ret = 0; + + if (!sensor->streaming) /* only during streaming */ + return 0; + + switch (id) { + case V4L2_CID_TOF_PHASE_SEQ: + case V4L2_CID_TOF_FREQ_MOD: + case V4L2_CID_TOF_TIME_INTEGRATION: + case V4L2_CID_VFLIP: + case V4L2_CID_HFLIP: + ret = mlx7502x_write8(&sensor->sd, + MLX7502X_PARAM_HOLD_REG, + hold, NULL); + break; + default: + break; + } + + return ret; +} + +static int mlx7502x_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct mlx7502x *sensor = container_of(ctrl->handler, + struct mlx7502x, + ctrl_handler); + struct v4l2_subdev *sd = &sensor->sd; + struct v4l2_subdev_state *state; + int ret = 0; + + if (!pm_runtime_get_if_in_use(sensor->dev)) + return 0; + + state = v4l2_subdev_get_locked_active_state(sd); + + ret = mlx7502x_hold(sensor, ctrl->id, 1); + if (ret < 0) + return ret; + + switch (ctrl->id) { + case V4L2_CID_TOF_PHASE_SEQ: + ret = mlx7502x_set_phase_seq(sensor, state, ctrl); + break; + case V4L2_CID_TOF_FREQ_MOD: + ret = mlx7502x_set_fmod(sensor, *ctrl->p_new.p_u32); + break; + case V4L2_CID_TOF_TIME_INTEGRATION: + ret = mlx7502x_set_tint(sensor, state, ctrl); + break; + case V4L2_CID_MLX7502X_OUTPUT_MODE: + ret = mlx7502x_update_hmax(sensor, + sensor->link_freq->val, + ctrl->val); + /* update format state */ + if (ret == 0) + mlx7502x_set_format(sd, state, NULL); + break; + case V4L2_CID_LINK_FREQ: + ret = mlx7502x_update_hmax(sensor, + ctrl->val, + sensor->output_mode->val); + break; + case V4L2_CID_VFLIP: + ret = mlx7502x_write8(sd, MLX7502X_VFLIP_REG, ctrl->val, NULL); + break; + case V4L2_CID_HFLIP: + ret = mlx7502x_write8(sd, MLX7502X_HFLIP_REG, ctrl->val, NULL); + break; + case V4L2_CID_CAMERA_TRIGGER: + ret = mlx7502x_write8(sd, MLX7502X_SW_TRIGGER_REG, + MLX7502X_SW_TRIGGER_TRIG, NULL); + break; + case V4L2_CID_CAMERA_TRIGGER_MODE: + ret = mlx7502x_set_trigger_mode(sensor, ctrl->val); + break; + default: + dev_err(sensor->dev, "Unknown id: %x\n", ctrl->id); + break; + } + + mlx7502x_hold(sensor, ctrl->id, 0); + pm_runtime_put_autosuspend(sensor->dev); + + return ret; +} + +static const struct v4l2_ctrl_ops mlx7502x_ctrl_ops = { + .s_ctrl = mlx7502x_s_ctrl, +}; + +static const struct v4l2_ctrl_config mlx7502x_phase_sequence = { + .ops = &mlx7502x_ctrl_ops, + .id = V4L2_CID_TOF_PHASE_SEQ, + .min = 0, + .max = 315, + .step = 45, + .def = 0, + .dims = { MLX7502X_PHASE_MAX_NUM }, +}; + +static const struct v4l2_ctrl_config mlx7502x_fmod = { + .ops = &mlx7502x_ctrl_ops, + .id = V4L2_CID_TOF_FREQ_MOD, + .min = 4000000, + .max = 100000000, + .step = 1000000, /* in Hz */ + .def = 40000000, + .dims = { 1 }, +}; + +static const struct v4l2_ctrl_config mlx7502x_tint = { + .ops = &mlx7502x_ctrl_ops, + .id = V4L2_CID_TOF_TIME_INTEGRATION, + .min = 5, + .max = 1000, + .step = 1, /* in us */ + .def = 198, + .dims = { MLX7502X_PHASE_MAX_NUM }, +}; + +static const struct v4l2_ctrl_config mlx7502x_output_mode = { + .ops = &mlx7502x_ctrl_ops, + .id = V4L2_CID_MLX7502X_OUTPUT_MODE, + .name = "Output mode", + .type = V4L2_CTRL_TYPE_MENU, + .max = ARRAY_SIZE(mlx7502x_ctrl_output) - 1, + .def = 0, + .qmenu = mlx7502x_ctrl_output, +}; + +static int mlx7502x_link_freq_init(struct mlx7502x *sensor) +{ + struct v4l2_ctrl_handler *hdl = &sensor->ctrl_handler; + const s64 *link_freq = sensor->cur_desc->link_freq_cfg->link_freq; + int i, j, link_freq_mask; + + link_freq_mask = 0; + for (i = 0; i < sensor->ep.nr_of_link_frequencies; i++) { + for (j = 0; j < MLX7502X_LINK_FREQ_N; j++) { + if (link_freq[j] == sensor->ep.link_frequencies[i]) + break; + } + + if (j == MLX7502X_LINK_FREQ_N) { + dev_err(sensor->dev, "no link frequency %lld supported\n", + link_freq[j]); + return -EINVAL; + } + + link_freq_mask |= (1 << j); + } + + sensor->link_freq = v4l2_ctrl_new_int_menu(hdl, &mlx7502x_ctrl_ops, + V4L2_CID_LINK_FREQ, + MLX7502X_LINK_FREQ_N - 1, + __fls(link_freq_mask), + link_freq); + + sensor->link_freq->menu_skip_mask = ~link_freq_mask; + + return 0; +} + +static int mlx7502x_ctrls_init(struct mlx7502x *sensor) +{ + struct v4l2_ctrl_handler *hdl; + int ret = 0; + + hdl = &sensor->ctrl_handler; + + ret = v4l2_ctrl_handler_init(hdl, 9); + if (ret) { + dev_err(sensor->dev, "Failed to init handler - %d\n", ret); + return ret; + } + + ret = mlx7502x_link_freq_init(sensor); + if (ret) + goto error_ctrls; + + v4l2_ctrl_new_std(hdl, &mlx7502x_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); + v4l2_ctrl_new_std(hdl, &mlx7502x_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0); + sensor->trigger = v4l2_ctrl_new_std(hdl, &mlx7502x_ctrl_ops, + V4L2_CID_CAMERA_TRIGGER, + 0, 0, 0, 0); + + sensor->trigger_mode = v4l2_ctrl_new_std_menu(hdl, &mlx7502x_ctrl_ops, + V4L2_CID_CAMERA_TRIGGER_MODE, + 2, 0, 0); + + v4l2_ctrl_new_custom(hdl, &mlx7502x_fmod, NULL); + sensor->phase_seq = v4l2_ctrl_new_custom(hdl, &mlx7502x_phase_sequence, + NULL); + + sensor->tint = v4l2_ctrl_new_custom(hdl, &mlx7502x_tint, NULL); + sensor->output_mode = v4l2_ctrl_new_custom(hdl, &mlx7502x_output_mode, + NULL); + __v4l2_ctrl_grab(sensor->trigger, true); + + if (hdl->error) { + dev_err(sensor->dev, "Error %d while adding controls\n", + hdl->error); + ret = hdl->error; + goto error_ctrls; + } + + sensor->sd.ctrl_handler = hdl; + return 0; + +error_ctrls: + v4l2_ctrl_handler_free(hdl); + return ret; +} + +/* + * ***************************************************************************** + * Probing + * ***************************************************************************** + */ +static int mlx7502x_fwnode_parse(struct mlx7502x *sensor, struct device *dev) +{ + struct fwnode_handle *endpoint; + int ret, num_data_lanes; + + endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL); + if (!endpoint) { + dev_err(dev, "endpoint node not found\n"); + return -EINVAL; + } + + ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &sensor->ep); + fwnode_handle_put(endpoint); + if (ret < 0) { + dev_err(dev, "parsing endpoint node failed\n"); + return ret; + } + + if (sensor->ep.bus_type != V4L2_MBUS_CSI2_DPHY) { + dev_err(dev, "invalid bus type, must be MIPI CSI2\n"); + ret = -EINVAL; + goto dt_ep_error; + } + + num_data_lanes = sensor->ep.bus.mipi_csi2.num_data_lanes; + if (num_data_lanes != 2 && num_data_lanes != 4) { + dev_err(dev, "invalid num_data_lanes, must be 2 or 4. But it was %d\n", + num_data_lanes); + ret = -EINVAL; + goto dt_ep_error; + } + + if (!sensor->ep.nr_of_link_frequencies) { + dev_err(dev, "missing link frequencies property\n"); + ret = -EINVAL; + goto dt_ep_error; + } + + return 0; + +dt_ep_error: + v4l2_fwnode_endpoint_free(&sensor->ep); + return ret; +} + +static int mlx7502x_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct mlx7502x *sensor; + struct v4l2_subdev *sd; + u32 xclk_rate; + int ret, i; + + sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL); + if (!sensor) + return -ENOMEM; + + if (dev_fwnode(dev)) + sensor->cur_desc = device_get_match_data(dev); + else + return -ENODEV; + + ret = mlx7502x_fwnode_parse(sensor, dev); + if (ret < 0) + return ret; + + sensor->xclk = devm_clk_get(dev, NULL); + if (IS_ERR(sensor->xclk)) { + dev_err(dev, "failed to get xclk\n"); + return PTR_ERR(sensor->xclk); + } + + xclk_rate = clk_get_rate(sensor->xclk); + if (xclk_rate != MLX7502X_XCLK_RATE) { + dev_err(dev, "only 8MHz clock is supported\n"); + return -EINVAL; + } + + for (i = 0; i < MLX7502X_NUM_SUPPLIES; i++) + sensor->supplies[i].supply = mlx7502x_supply_names[i]; + + ret = devm_regulator_bulk_get(dev, MLX7502X_NUM_SUPPLIES, + sensor->supplies); + if (ret) + return ret; + + sensor->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(sensor->reset)) { + dev_err(dev, "failed to get reset\n"); + return PTR_ERR(sensor->reset); + } + + sensor->dev = dev; + sd = &sensor->sd; + v4l2_i2c_subdev_init(sd, client, &mlx7502x_subdev_ops); + sd->internal_ops = &mlx7502x_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; + + sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; + sensor->pad.flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&sd->entity, 1, &sensor->pad); + if (ret < 0) + goto error_ep; + + sensor->binning_mode = &binning_mode[0]; + + ret = mlx7502x_ctrls_init(sensor); + if (ret < 0) + goto error_init; + + sd->state_lock = sensor->ctrl_handler.lock; + + v4l2_subdev_init_finalize(sd); + + pm_runtime_enable(dev); + + ret = v4l2_async_register_subdev(sd); + if (ret < 0) + goto error_pm; + + /* configure to use autosuspend, delay 1s */ + pm_runtime_set_autosuspend_delay(dev, 1000); + pm_runtime_use_autosuspend(dev); + + dev_dbg(dev, "Melexis ToF camera driver probed\n"); + + return 0; + +error_pm: + pm_runtime_disable(dev); +error_init: + v4l2_subdev_cleanup(sd); + media_entity_cleanup(&sd->entity); +error_ep: + v4l2_fwnode_endpoint_free(&sensor->ep); + return ret; +} + +static void mlx7502x_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct mlx7502x *sensor = to_mlx7502x(sd); + + pm_runtime_disable(&client->dev); + if (!pm_runtime_status_suspended(&client->dev)) + mlx7502x_power_off(sensor); + pm_runtime_set_suspended(&client->dev); + + v4l2_fwnode_endpoint_free(&sensor->ep); + v4l2_async_unregister_subdev(sd); + v4l2_ctrl_handler_free(&sensor->ctrl_handler); + + v4l2_subdev_cleanup(sd); + media_entity_cleanup(&sensor->sd.entity); +} + +static const struct dev_pm_ops mlx7502x_pm_ops = { + SET_RUNTIME_PM_OPS(mlx7502x_runtime_suspend, + mlx7502x_runtime_resume, + NULL) +}; + +static const struct of_device_id mlx7502x_of_match[] = { + { .compatible = "melexis,mlx75026", .data = &mlx75026 }, + { .compatible = "melexis,mlx75027", .data = &mlx75027 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mlx7502x_of_match); + +static struct i2c_driver mlx7502x_driver = { + .driver = { + .of_match_table = mlx7502x_of_match, + .name = "mlx7502x", + .pm = &mlx7502x_pm_ops, + }, + .probe = mlx7502x_probe, + .remove = mlx7502x_remove, +}; + +module_i2c_driver(mlx7502x_driver); + +MODULE_AUTHOR("Andrii Kyselov "); +MODULE_AUTHOR("Volodymyr Kharuk "); +MODULE_DESCRIPTION("A low-level driver for Melexis TOF sensors"); +MODULE_LICENSE("GPL");