From patchwork Fri Nov 25 15:31:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petko Manolov X-Patchwork-Id: 87816 Received: from vger.kernel.org ([23.128.96.18]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1oyafu-00CzEZ-Hd; Fri, 25 Nov 2022 15:31:34 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229581AbiKYPbc (ORCPT + 1 other); Fri, 25 Nov 2022 10:31:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53050 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229502AbiKYPbb (ORCPT ); Fri, 25 Nov 2022 10:31:31 -0500 Received: from mail-ej1-x634.google.com (mail-ej1-x634.google.com [IPv6:2a00:1450:4864:20::634]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9487025E8A for ; Fri, 25 Nov 2022 07:31:30 -0800 (PST) Received: by mail-ej1-x634.google.com with SMTP id i10so11094395ejg.6 for ; Fri, 25 Nov 2022 07:31:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=konsulko.com; s=google; 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=/3xizgLpKf9eakyGEdImT/fgj0br4xdsRLx7qxrVAJk=; b=lUD2Fv7+u3BaFuP7zMy1MvD5Q7ePWKHm4fxwoy9PRTLhn/VDNB5Skeg3bWOlT6m/5s F2fIulQ4bAQNqqEEe7eU4Ywo7r34xp76GuQ2NkoCve2b0YgdVS2iuHQzs1UPsXprE6gD YBujOZj4ky5CeKX1v9kBfRd/dgIXUThmq9YDc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=/3xizgLpKf9eakyGEdImT/fgj0br4xdsRLx7qxrVAJk=; b=MUqJUYPmHWqS/Kxbh0NhHflwH/DYNFwHsNzM6nen6J78BPmD5FqsLGQmAe3pk1n6dY BgJyw0jhUwwrx1ZDZLRnOHgK8cdl5aq/lEWAETryOXDNCT1fw6iL1bkGsWY7rZGT1WGu oj/5xNr7M8QxBmjpkM4gzJF8wBnlD5joPkEJGXSKghGN69y09isJbeGBBUqPXlgqhnBf MrH9WynFck+z7XyAlczPGefZk7Fsc2t+2JpOUNfmN+uonGHqsBhENuH+CggtvfEogxrN ezK6ohiHH+LRRe8vvjpxICp040wXGV18Zd7qdNE4uhzHcIiw2aXc4eC8MA8OlS7k/sOw plyw== X-Gm-Message-State: ANoB5pmtfF8un4ZuGbiaS12XiLu/MVqs2xJ73o4ShcA9GNrowkiduKuY cHE8biXBK2mG/ypJVTZ3lTSDAaPGTOoghg== X-Google-Smtp-Source: AA0mqf43dwfoXiANWdgy1aNIYfL6xmTo3iEe+IpTC6yTfmDab0WZYwO9i6/1Y3ROrpOzXChJ8HOJgw== X-Received: by 2002:a17:906:8e0a:b0:7b9:bef6:3eea with SMTP id rx10-20020a1709068e0a00b007b9bef63eeamr11691882ejc.487.1669390288733; Fri, 25 Nov 2022 07:31:28 -0800 (PST) Received: from tone.k.g (lan.nucleusys.com. [92.247.61.126]) by smtp.gmail.com with ESMTPSA id p10-20020aa7cc8a000000b0045b4b67156fsm1878435edt.45.2022.11.25.07.31.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 25 Nov 2022 07:31:28 -0800 (PST) From: Petko Manolov To: linux-media@vger.kernel.org Cc: laurent.pinchart@ideasonboard.com, sakari.ailus@iki.fi, Petko Manolov Subject: [PATCH v1 1/5] DT bindings for imx492 Date: Fri, 25 Nov 2022 17:31:16 +0200 Message-Id: <20221125153120.541298-2-petko.manolov@konsulko.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221125153120.541298-1-petko.manolov@konsulko.com> References: <20221125153120.541298-1-petko.manolov@konsulko.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-LSpam-Score: -2.5 (--) X-LSpam-Report: No, score=-2.5 required=5.0 tests=BAYES_00=-1.9,DKIM_SIGNED=0.1,DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1 autolearn=ham autolearn_force=no Here goes the DT bindings file. Signed-off-by: Petko Manolov --- .../bindings/media/i2c/sony,imx492.yaml | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/sony,imx492.yaml diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx492.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx492.yaml new file mode 100644 index 000000000000..f4feef17c677 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/sony,imx492.yaml @@ -0,0 +1,101 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/i2c/sony,imx492.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Sony imx492 Sensor + +maintainers: + - Petko Manolov + +description: + + imx492 is a diagonal 23.1 mm (Type 1.4) CMOS image sensor with color or + monochrome square pixel array and approximately 47.08 M effective pixels. + 12-bit digital output makes it possible to output the signals with high + definition for moving pictures. It is programmable through I2C interface. The + I2C client address can be either 0x10 or 0x1a depending on SLASEL pin. Image + data is sent through MIPI CSI-2. + +properties: + compatible: + const: sony,imx492 + reg: + description: I2C address + maxItems: 1 + + assigned-clocks: true + assigned-clock-parents: true + assigned-clock-rates: true + + clocks: + description: Clock frequency 6MHz, 12MHz, 18MHz and 24MHz + maxItems: 1 + + dovdd-supply: + description: Interface power supply. + + avdd-supply: + description: Analog power supply. + + dvdd-supply: + description: Digital power supply. + + reset-gpios: + description: Reference to the GPIO connected to the XCLR pin, if any. + maxItems: 1 + + port: + additionalProperties: false + $ref: /schemas/graph.yaml#/$defs/port-base + + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: true + link-frequencies: true + + required: + - data-lanes + - link-frequencies + + required: + - endpoint + +required: + - compatible + - reg + - clocks + - port + +additionalProperties: false + +examples: + - | + i2c0 { + #address-cells = <1>; + #size-cells = <0>; + + camera@10 { + compatible = "sony,imx492"; + reg = <0x10>; + clocks = <&imx492_clk>; + + assigned-clocks = <&imx492_clk>; + assigned-clock-parents = <&imx492_clk_parent>; + assigned-clock-rates = <24000000>; + + port { + imx492: endpoint { + remote-endpoint = <&cam>; + data-lanes = <1 2 3 4>; + link-frequencies = /bits/ 64 <600000000>; + }; + }; + }; + }; +... From patchwork Fri Nov 25 15:31:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petko Manolov X-Patchwork-Id: 87817 Received: from vger.kernel.org ([23.128.96.18]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1oyafv-00CzEZ-JJ; Fri, 25 Nov 2022 15:31:36 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229610AbiKYPbe (ORCPT + 1 other); Fri, 25 Nov 2022 10:31:34 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53066 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229502AbiKYPbd (ORCPT ); Fri, 25 Nov 2022 10:31:33 -0500 Received: from mail-ej1-x62c.google.com (mail-ej1-x62c.google.com [IPv6:2a00:1450:4864:20::62c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D884325E8A for ; Fri, 25 Nov 2022 07:31:31 -0800 (PST) Received: by mail-ej1-x62c.google.com with SMTP id kt23so11086239ejc.7 for ; Fri, 25 Nov 2022 07:31:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=konsulko.com; s=google; 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=injdiHNm2C3HxXCfswOPFzoWoCDYFn/DG5RZbwSMwwY=; b=DwQAuP8c5SPtER4n+iHLxA03TQ4ZbQXVHil5PGAJitnwRSNeDhd8BGDcT2djzM+dJ/ MIpC7QY6BLa/5ZQdyrczKuQiwxwyPLfsuCvngd5XI8eHL7MYlLS4bajWUfY5IbtXGayL 3b2yOYVTczGyyzmpgtRwR5KHeXLsLhIIWpjQ0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=injdiHNm2C3HxXCfswOPFzoWoCDYFn/DG5RZbwSMwwY=; b=AzUmj6zBdKjNqFEabmdkQdQk7NA2nZBS0mpkAXjHz036gYHSf/hmYjhDvN6oAWk57J o6eFS+XB0VIhrzc9GW4kc2aMWTxK6/Sk4rZ4zCHw1DXcAQm0AayXoEHrdbZLbuV82niM mroJZR5q+0AgvYeRhlwLC9q1PXo+opJ53wlWF6r0bEI13wWHIeXCjaZaWEwgW/chP9zS C6QijppLS0L1K+Ns7/vVdBk6olWdRVDtkMcFsY+PZGUgGsMKWEanKGv8djTPUB5kQp/0 oI0+L6UFvQ3Fx8bozNWV1Pl9F+xRWyjfdpSjOy7r0gjJoGzGxswFixmB+CH8elDfwVjj XMeA== X-Gm-Message-State: ANoB5pnO3HmVz1telImUeqy4ZG1eUNVrwFoVl51mu+KGqvqO6cgWIqHF 7iN1RrelgCtsC+QhpPvC0/4lUU5zTC5zCQ== X-Google-Smtp-Source: AA0mqf5tTjzLWXZkENVU0PcyiBIHy11Nbsk1uxGlfZbE0uuTzYT7CKJvttnUXt9uMr55H7fCy6KMKg== X-Received: by 2002:a17:906:2345:b0:7ad:adfe:1ceb with SMTP id m5-20020a170906234500b007adadfe1cebmr24539346eja.89.1669390289853; Fri, 25 Nov 2022 07:31:29 -0800 (PST) Received: from tone.k.g (lan.nucleusys.com. [92.247.61.126]) by smtp.gmail.com with ESMTPSA id p10-20020aa7cc8a000000b0045b4b67156fsm1878435edt.45.2022.11.25.07.31.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 25 Nov 2022 07:31:29 -0800 (PST) From: Petko Manolov To: linux-media@vger.kernel.org Cc: laurent.pinchart@ideasonboard.com, sakari.ailus@iki.fi, Petko Manolov Subject: [PATCH v1 2/5] media: i2c: imx492: driver's header Date: Fri, 25 Nov 2022 17:31:17 +0200 Message-Id: <20221125153120.541298-3-petko.manolov@konsulko.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221125153120.541298-1-petko.manolov@konsulko.com> References: <20221125153120.541298-1-petko.manolov@konsulko.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-LSpam-Score: -2.5 (--) X-LSpam-Report: No, score=-2.5 required=5.0 tests=BAYES_00=-1.9,DKIM_SIGNED=0.1,DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1 autolearn=ham autolearn_force=no The header. For the moment only two modes are supported. Signed-off-by: Petko Manolov --- drivers/media/i2c/imx492.h | 555 +++++++++++++++++++++++++++++++++++++ 1 file changed, 555 insertions(+) create mode 100644 drivers/media/i2c/imx492.h diff --git a/drivers/media/i2c/imx492.h b/drivers/media/i2c/imx492.h new file mode 100644 index 000000000000..301fd66c77d5 --- /dev/null +++ b/drivers/media/i2c/imx492.h @@ -0,0 +1,555 @@ +#ifndef __imx492_h__ +#define __imx492_h__ + +struct imx492_reg { + u16 address; + u8 val; +}; + +static const struct imx492_reg mode_17to9_regs[] = { + { 0x3033, 0x30 }, + { 0x303c, 0x01 }, + { 0x31e8, 0xa0 }, + { 0x31f4, 0x01 }, + { 0x31e9, 0x00 }, + { 0x3122, 0x02 }, + { 0x3129, 0x90 }, + { 0x312a, 0x02 }, + { 0x311f, 0x00 }, + { 0x3123, 0x00 }, + { 0x3124, 0x00 }, + { 0x3125, 0x01 }, + { 0x3127, 0x02 }, + { 0x312d, 0x02 }, + { 0x3000, 0x12 }, + { 0x310b, 0x00 }, + { 0x3004, 0x1c }, + { 0x3005, 0x06 }, + { 0x3006, 0x00 }, + { 0x3007, 0xa7 }, + { 0x3047, 0x02 }, + { 0x304e, 0x0b }, + { 0x304f, 0x2a }, + { 0x3052, 0xee }, + { 0x3062, 0x25 }, + { 0x3064, 0x78 }, + { 0x3065, 0x33 }, + { 0x3066, 0x64 }, + { 0x3067, 0x71 }, + { 0x307e, 0x07 }, + { 0x3081, 0x00 }, + { 0x3088, 0x75 }, + { 0x308a, 0x09 }, + { 0x308c, 0x61 }, + { 0x30ef, 0x01 }, + { 0x3146, 0x00 }, + { 0x31f5, 0x01 }, + { 0x3234, 0x32 }, + { 0x3248, 0xbc }, + { 0x3250, 0xbc }, + { 0x3258, 0xbc }, + { 0x3260, 0xbc }, + { 0x3274, 0x13 }, + { 0x3276, 0x00 }, + { 0x3277, 0x00 }, + { 0x327c, 0x13 }, + { 0x327e, 0x00 }, + { 0x327f, 0x00 }, + { 0x3284, 0x13 }, + { 0x3286, 0x00 }, + { 0x3287, 0x00 }, + { 0x328c, 0x13 }, + { 0x328e, 0x00 }, + { 0x328f, 0x00 }, + { 0x32ae, 0x00 }, + { 0x32af, 0x00 }, + { 0x32ca, 0x5a }, + { 0x332c, 0x00 }, + { 0x332f, 0x00 }, + { 0x334a, 0x00 }, + { 0x334c, 0x01 }, + { 0x3352, 0x50 }, + { 0x3356, 0x4f }, + { 0x335a, 0x79 }, + { 0x335e, 0x56 }, + { 0x3360, 0x6a }, + { 0x336a, 0x56 }, + { 0x33d6, 0x79 }, + { 0x340c, 0x6e }, + { 0x3448, 0x7e }, + { 0x348e, 0x6f }, + { 0x3492, 0x11 }, + { 0x34c4, 0x5a }, + { 0x3506, 0x56 }, + { 0x350c, 0x56 }, + { 0x350e, 0x58 }, + { 0x353d, 0x10 }, + { 0x3549, 0x04 }, + { 0x355d, 0x03 }, + { 0x355e, 0x03 }, + { 0x3574, 0x56 }, + { 0x357f, 0x0c }, + { 0x3580, 0x0a }, + { 0x3581, 0x08 }, + { 0x3583, 0x72 }, + { 0x3587, 0x01 }, + { 0x35b6, 0x00 }, + { 0x35b8, 0x00 }, + { 0x35d0, 0x5e }, + { 0x35d4, 0x63 }, + { 0x366a, 0x04 }, + { 0x366b, 0x04 }, + { 0x366c, 0x00 }, + { 0x366d, 0x00 }, + { 0x366e, 0x00 }, + { 0x366f, 0x00 }, + { 0x3670, 0x00 }, + { 0x3671, 0x05 }, + { 0x3676, 0x83 }, + { 0x3677, 0x03 }, + { 0x3678, 0x00 }, + { 0x3679, 0x04 }, + { 0x367a, 0x2c }, + { 0x367b, 0x05 }, + { 0x367d, 0x06 }, + { 0x367e, 0xff }, + { 0x367f, 0x06 }, + { 0x3680, 0x4b }, + { 0x3688, 0x05 }, + { 0x3690, 0x27 }, + { 0x3692, 0x65 }, + { 0x3694, 0x4f }, + { 0x3696, 0xa1 }, + { 0x36bc, 0x00 }, + { 0x371c, 0x02 }, + { 0x372f, 0x3c }, + { 0x3730, 0x01 }, + { 0x3732, 0xb8 }, + { 0x3734, 0x4a }, + { 0x3736, 0x57 }, + { 0x3738, 0x4d }, + { 0x3744, 0x0f }, + { 0x375b, 0x01 }, + { 0x382b, 0x68 }, + { 0x38b3, 0x00 }, + { 0x3910, 0x90 }, + { 0x3911, 0x70 }, + { 0x3912, 0x92 }, + { 0x3913, 0x24 }, + { 0x3914, 0x93 }, + { 0x3915, 0x0b }, + { 0x3916, 0x01 }, + { 0x3918, 0x04 }, + { 0x391c, 0x90 }, + { 0x391d, 0x05 }, + { 0x3920, 0x96 }, + { 0x3921, 0x06 }, + { 0x3a2a, 0x01 }, + { 0x3a7a, 0x01 }, + { 0x3a7b, 0x01 }, + { 0x3acb, 0x06 }, + { 0x3c08, 0x3f }, + { 0x3c0c, 0x1b }, + { 0x3e80, 0x14 }, + { 0x3e82, 0x30 }, + { 0x3e84, 0x0c }, + { 0x3e85, 0x06 }, + { 0x3e86, 0xfc }, + { 0x3e87, 0x10 }, + { 0x3e88, 0x03 }, + { 0x3e89, 0xfe }, + { 0x3e8a, 0x01 }, + { 0x3e8b, 0x06 }, + { 0x3e8e, 0x03 }, + { 0x3e8f, 0xfe }, + { 0x3e90, 0x01 }, + { 0x3e91, 0x06 }, + { 0x3e94, 0x33 }, + { 0x3e95, 0x01 }, + { 0x3e96, 0x19 }, + { 0x3e98, 0x30 }, + { 0x3e9a, 0x11 }, + { 0x3e9b, 0x06 }, + { 0x3e9c, 0xfc }, + { 0x3e9d, 0x10 }, + { 0x3e9e, 0xfe }, + { 0x3e9f, 0x03 }, + { 0x3ea0, 0x06 }, + { 0x3ea3, 0x01 }, + { 0x3ea4, 0xfe }, + { 0x3ea5, 0x03 }, + { 0x3ea6, 0x06 }, + { 0x3ea9, 0x33 }, + { 0x3eaa, 0x00 }, + { 0x3eab, 0x08 }, + { 0x3eac, 0x08 }, + { 0x3ead, 0x01 }, + { 0x3eae, 0x08 }, + { 0x3eaf, 0x08 }, + { 0x3eb0, 0x00 }, + { 0x3eb1, 0x10 }, + { 0x3eb2, 0x10 }, + { 0x3eb3, 0x01 }, + { 0x3eb4, 0x10 }, + { 0x3eb5, 0x10 }, + { 0x3eb6, 0x00 }, + { 0x3eb7, 0x00 }, + { 0x3eb8, 0x00 }, + { 0x3eb9, 0x00 }, + { 0x3eba, 0x00 }, + { 0x3ebb, 0x00 }, + { 0x3ec0, 0x54 }, + { 0x3ecc, 0x04 }, + { 0x3ecd, 0x04 }, + { 0x3ed0, 0xf0 }, + { 0x3ed1, 0x20 }, + { 0x3ed2, 0x0b }, + { 0x3ed3, 0x04 }, + { 0x3ed5, 0x13 }, + { 0x3ed6, 0x00 }, + { 0x3ed9, 0x0f }, + { 0x3ee4, 0x02 }, + { 0x3ee5, 0x02 }, + { 0x3ee7, 0x00 }, + { 0x3ef6, 0x00 }, + { 0x3ef8, 0x10 }, + { 0x3efa, 0x00 }, + { 0x3efc, 0x10 }, + { 0x3134, 0xa7 }, + { 0x3135, 0x00 }, + { 0x3136, 0x9f }, + { 0x3137, 0x00 }, + { 0x3138, 0x6f }, + { 0x3139, 0x00 }, + { 0x313a, 0x5f }, + { 0x313b, 0x00 }, + { 0x313c, 0x5f }, + { 0x313d, 0x00 }, + { 0x313e, 0x7f }, + { 0x313f, 0x01 }, + { 0x3140, 0x6f }, + { 0x3141, 0x00 }, + { 0x3142, 0x4f }, + { 0x3143, 0x00 }, + { 0x300e, 0x00 }, + { 0x300f, 0x00 }, + { 0x302c, 0x0c }, + { 0x302d, 0x00 }, + { 0x3034, 0x01 }, + { 0x3035, 0x01 }, + { 0x3036, 0x64 }, + { 0x3037, 0x00 }, + { 0x3038, 0xc8 }, + { 0x3039, 0x00 }, + { 0x3084, 0x4e }, + { 0x3085, 0x04 }, + { 0x3086, 0x4e }, + { 0x3087, 0x04 }, + { 0x30a9, 0xe0 }, + { 0x30aa, 0x2e }, + { 0x30ab, 0x00 }, + { 0x30ac, 0x48 }, + { 0x30ad, 0x0d }, + { 0x30e2, 0x00 }, + { 0x312f, 0x20 }, + { 0x3130, 0x1c }, + { 0x3131, 0x11 }, + { 0x3132, 0xfc }, + { 0x3133, 0x10 }, + { 0x3a54, 0xf0 }, + { 0x3a55, 0x20 }, + { 0x3a43, 0x01 }, + { 0x3a3b, 0x00 }, + { 0x3042, 0x32 }, + { 0x3092, 0x00 }, + { 0x30dd, 0x00 }, + { 0x30de, 0x00 }, + { 0x30df, 0x00 }, + { 0x30e0, 0x00 }, + { 0x30e1, 0x00 }, + { 0x332c, 0x00 }, + { 0x332d, 0x00 }, + { 0x334a, 0x00 }, + { 0x334b, 0x00 }, + { 0x35b6, 0x00 }, + { 0x35b7, 0x00 }, + { 0x35b8, 0x00 }, + { 0x35b9, 0x00 }, + { 0x36bc, 0x00 }, + { 0x36bd, 0x00 }, +}; + +static const struct imx492_reg mode_all_regs[] = { + { 0x3033, 0x30 }, + { 0x303c, 0x01 }, + { 0x31e8, 0xa0 }, + { 0x31f4, 0x01 }, + { 0x31e9, 0x00 }, + { 0x3122, 0x02 }, + { 0x3129, 0x90 }, + { 0x312a, 0x02 }, + { 0x311f, 0x00 }, + { 0x3123, 0x00 }, + { 0x3124, 0x00 }, + { 0x3125, 0x01 }, + { 0x3127, 0x02 }, + { 0x312d, 0x02 }, + { 0x3000, 0x12 }, + { 0x310b, 0x00 }, + { 0x3004, 0x1c }, + { 0x3005, 0x06 }, + { 0x3006, 0x00 }, + { 0x3007, 0xa7 }, + { 0x3047, 0x02 }, + { 0x304e, 0x0b }, + { 0x304f, 0x2a }, + { 0x3052, 0xee }, + { 0x3062, 0x25 }, + { 0x3064, 0x78 }, + { 0x3065, 0x33 }, + { 0x3066, 0x64 }, + { 0x3067, 0x71 }, + { 0x307e, 0x07 }, + { 0x3081, 0x00 }, + { 0x3088, 0x75 }, + { 0x308a, 0x09 }, + { 0x308c, 0x61 }, + { 0x30ef, 0x01 }, + { 0x3146, 0x00 }, + { 0x31f5, 0x01 }, + { 0x3234, 0x32 }, + { 0x3248, 0xbc }, + { 0x3250, 0xbc }, + { 0x3258, 0xbc }, + { 0x3260, 0xbc }, + { 0x3274, 0x13 }, + { 0x3276, 0x00 }, + { 0x3277, 0x00 }, + { 0x327c, 0x13 }, + { 0x327e, 0x00 }, + { 0x327f, 0x00 }, + { 0x3284, 0x13 }, + { 0x3286, 0x00 }, + { 0x3287, 0x00 }, + { 0x328c, 0x13 }, + { 0x328e, 0x00 }, + { 0x328f, 0x00 }, + { 0x32ae, 0x00 }, + { 0x32af, 0x00 }, + { 0x32ca, 0x5a }, + { 0x332c, 0x00 }, + { 0x332f, 0x00 }, + { 0x334a, 0x00 }, + { 0x334c, 0x01 }, + { 0x3352, 0x50 }, + { 0x3356, 0x4f }, + { 0x335a, 0x79 }, + { 0x335e, 0x56 }, + { 0x3360, 0x6a }, + { 0x336a, 0x56 }, + { 0x33d6, 0x79 }, + { 0x340c, 0x6e }, + { 0x3448, 0x7e }, + { 0x348e, 0x6f }, + { 0x3492, 0x11 }, + { 0x34c4, 0x5a }, + { 0x3506, 0x56 }, + { 0x350c, 0x56 }, + { 0x350e, 0x58 }, + { 0x353d, 0x10 }, + { 0x3549, 0x04 }, + { 0x355d, 0x03 }, + { 0x355e, 0x03 }, + { 0x3574, 0x56 }, + { 0x357f, 0x0c }, + { 0x3580, 0x0a }, + { 0x3581, 0x08 }, + { 0x3583, 0x72 }, + { 0x3587, 0x01 }, + { 0x35b6, 0x00 }, + { 0x35b8, 0x00 }, + { 0x35d0, 0x5e }, + { 0x35d4, 0x63 }, + { 0x366a, 0x04 }, + { 0x366b, 0x04 }, + { 0x366c, 0x00 }, + { 0x366d, 0x00 }, + { 0x366e, 0x00 }, + { 0x366f, 0x00 }, + { 0x3670, 0x00 }, + { 0x3671, 0x05 }, + { 0x3676, 0x83 }, + { 0x3677, 0x03 }, + { 0x3678, 0x00 }, + { 0x3679, 0x04 }, + { 0x367a, 0x2c }, + { 0x367b, 0x05 }, + { 0x367d, 0x06 }, + { 0x367e, 0xff }, + { 0x367f, 0x06 }, + { 0x3680, 0x4b }, + { 0x3688, 0x05 }, + { 0x3690, 0x27 }, + { 0x3692, 0x65 }, + { 0x3694, 0x4f }, + { 0x3696, 0xa1 }, + { 0x36bc, 0x00 }, + { 0x371c, 0x02 }, + { 0x372f, 0x3c }, + { 0x3730, 0x01 }, + { 0x3732, 0xb8 }, + { 0x3734, 0x4a }, + { 0x3736, 0x57 }, + { 0x3738, 0x4d }, + { 0x3744, 0x0f }, + { 0x375b, 0x01 }, + { 0x382b, 0x68 }, + { 0x38b3, 0x00 }, + { 0x3910, 0x90 }, + { 0x3911, 0x70 }, + { 0x3912, 0x92 }, + { 0x3913, 0x24 }, + { 0x3914, 0x93 }, + { 0x3915, 0x0b }, + { 0x3916, 0x01 }, + { 0x3918, 0x04 }, + { 0x391c, 0x90 }, + { 0x391d, 0x05 }, + { 0x3920, 0x96 }, + { 0x3921, 0x06 }, + { 0x3a2a, 0x01 }, + { 0x3a7a, 0x01 }, + { 0x3a7b, 0x01 }, + { 0x3acb, 0x06 }, + { 0x3c08, 0x3f }, + { 0x3c0c, 0x1b }, + { 0x3e80, 0x14 }, + { 0x3e82, 0x30 }, + { 0x3e84, 0x0c }, + { 0x3e85, 0x06 }, + { 0x3e86, 0xfc }, + { 0x3e87, 0x10 }, + { 0x3e88, 0x03 }, + { 0x3e89, 0xfe }, + { 0x3e8a, 0x01 }, + { 0x3e8b, 0x06 }, + { 0x3e8e, 0x03 }, + { 0x3e8f, 0xfe }, + { 0x3e90, 0x01 }, + { 0x3e91, 0x06 }, + { 0x3e94, 0x33 }, + { 0x3e95, 0x01 }, + { 0x3e96, 0x19 }, + { 0x3e98, 0x30 }, + { 0x3e9a, 0x11 }, + { 0x3e9b, 0x06 }, + { 0x3e9c, 0xfc }, + { 0x3e9d, 0x10 }, + { 0x3e9e, 0xfe }, + { 0x3e9f, 0x03 }, + { 0x3ea0, 0x06 }, + { 0x3ea3, 0x01 }, + { 0x3ea4, 0xfe }, + { 0x3ea5, 0x03 }, + { 0x3ea6, 0x06 }, + { 0x3ea9, 0x33 }, + { 0x3eaa, 0x00 }, + { 0x3eab, 0x08 }, + { 0x3eac, 0x08 }, + { 0x3ead, 0x01 }, + { 0x3eae, 0x08 }, + { 0x3eaf, 0x08 }, + { 0x3eb0, 0x00 }, + { 0x3eb1, 0x10 }, + { 0x3eb2, 0x10 }, + { 0x3eb3, 0x01 }, + { 0x3eb4, 0x10 }, + { 0x3eb5, 0x10 }, + { 0x3eb6, 0x00 }, + { 0x3eb7, 0x00 }, + { 0x3eb8, 0x00 }, + { 0x3eb9, 0x00 }, + { 0x3eba, 0x00 }, + { 0x3ebb, 0x00 }, + { 0x3ec0, 0x54 }, + { 0x3ecc, 0x04 }, + { 0x3ecd, 0x04 }, + { 0x3ed0, 0xf0 }, + { 0x3ed1, 0x20 }, + { 0x3ed2, 0x0b }, + { 0x3ed3, 0x04 }, + { 0x3ed5, 0x13 }, + { 0x3ed6, 0x00 }, + { 0x3ed9, 0x0f }, + { 0x3ee4, 0x02 }, + { 0x3ee5, 0x02 }, + { 0x3ee7, 0x00 }, + { 0x3ef6, 0x00 }, + { 0x3ef8, 0x10 }, + { 0x3efa, 0x00 }, + { 0x3efc, 0x10 }, + { 0x3134, 0xa7 }, + { 0x3135, 0x00 }, + { 0x3136, 0x9f }, + { 0x3137, 0x00 }, + { 0x3138, 0x6f }, + { 0x3139, 0x00 }, + { 0x313a, 0x5f }, + { 0x313b, 0x00 }, + { 0x313c, 0x5f }, + { 0x313d, 0x00 }, + { 0x313e, 0x7f }, + { 0x313f, 0x01 }, + { 0x3140, 0x6f }, + { 0x3141, 0x00 }, + { 0x3142, 0x4f }, + { 0x3143, 0x00 }, + { 0x300e, 0x00 }, + { 0x300f, 0x00 }, + { 0x302c, 0x0c }, + { 0x302d, 0x00 }, + { 0x3034, 0x01 }, + { 0x3035, 0x01 }, + { 0x3036, 0x64 }, + { 0x3037, 0x00 }, + { 0x3038, 0xc8 }, + { 0x3039, 0x00 }, + { 0x3084, 0x4e }, + { 0x3085, 0x04 }, + { 0x3086, 0x4e }, + { 0x3087, 0x04 }, + { 0x30a9, 0xe0 }, + { 0x30aa, 0x2e }, + { 0x30ab, 0x00 }, + { 0x30ac, 0x48 }, + { 0x30ad, 0x0d }, + { 0x30e2, 0x00 }, + { 0x312f, 0x20 }, + { 0x3130, 0x1c }, + { 0x3131, 0x11 }, + { 0x3132, 0xfc }, + { 0x3133, 0x10 }, + { 0x3a54, 0xf0 }, + { 0x3a55, 0x20 }, + { 0x3a43, 0x01 }, + { 0x3a3b, 0x00 }, + { 0x3042, 0x32 }, + { 0x3092, 0x00 }, + { 0x30dd, 0x00 }, + { 0x30de, 0x00 }, + { 0x30df, 0x00 }, + { 0x30e0, 0x00 }, + { 0x30e1, 0x00 }, + { 0x332c, 0x00 }, + { 0x332d, 0x00 }, + { 0x334a, 0x00 }, + { 0x334b, 0x00 }, + { 0x35b6, 0x00 }, + { 0x35b7, 0x00 }, + { 0x35b8, 0x00 }, + { 0x35b9, 0x00 }, + { 0x36bc, 0x00 }, + { 0x36bd, 0x00 }, +}; + +#endif /* __imx492_h__ */ From patchwork Fri Nov 25 15:31:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petko Manolov X-Patchwork-Id: 87819 Received: from vger.kernel.org ([23.128.96.18]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1oyafy-00CzEZ-09; Fri, 25 Nov 2022 15:31:39 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229625AbiKYPbf (ORCPT + 1 other); Fri, 25 Nov 2022 10:31:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53080 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229622AbiKYPbf (ORCPT ); Fri, 25 Nov 2022 10:31:35 -0500 Received: from mail-ej1-x634.google.com (mail-ej1-x634.google.com [IPv6:2a00:1450:4864:20::634]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 791822D1DD for ; Fri, 25 Nov 2022 07:31:32 -0800 (PST) Received: by mail-ej1-x634.google.com with SMTP id i10so11094719ejg.6 for ; Fri, 25 Nov 2022 07:31:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=konsulko.com; s=google; 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=QGiPh5MLAV8F3tSeRFMZLdYIWr+o1wQ+LqC9b3cIhXY=; b=GFQLyU14FvWhzwfAWM4DqLwWKYIImUKCfnnle/yTPZzNTrv0M7UF1no/F/Hilcw2dl hNuU8nc7lpuVB0QZVFC9BFfiwQQkLY93f1ZRGNHuhCzIRbifwB5Qj3Y1Xg1Bb0fVYot6 Dg3yJa5q+vfZhPuSporRrI8hOXxLakDligYBQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=QGiPh5MLAV8F3tSeRFMZLdYIWr+o1wQ+LqC9b3cIhXY=; b=KGJLywCG276x90cUQK4MBqeaRvz1bs+oS4l1Eeo8LCO+LZ3mIRLoUs9FRSkrbq7zlg 1gv5BDG9SQp7pazEGd6W5it3mOfH/B/YHpTlN9SX6KU1n67jA1wAhFRMCqUfaKt3sHLy H2sdfiVekDoDNlo87zP/Ew1ABFebBSGUaOOmVQGh0bzwQvP8V2kY8kjG1iRbZFD43d7X k60IDHWUM1KrjD+5IHpIwJTneTdEpFVh0CAuZfh75zABYev3ihUyumctIngW8pbXkgjj uWT0AcVvpDDNBNe0u+OaagMtpp3UwHpZw2S1R7RGOaxpkR70pRDco+tDuyXtMiHdEnuF Ha8w== X-Gm-Message-State: ANoB5plwx6owf38qOyp+3FpgcLcmeQaLsfq7USYyKiMQQ4/QF2CpRgzg qfFOKuwotrj4LsDqzU425liE8GxNi/4MEA== X-Google-Smtp-Source: AA0mqf46+7atFa4ENV3w7rAkZoBWmZFRqFboh9UorMfoxJnxvpNW2swGCaGIFbzpwo7RhiCjJdsbEw== X-Received: by 2002:a17:906:1445:b0:7a1:6786:444f with SMTP id q5-20020a170906144500b007a16786444fmr15677937ejc.409.1669390291111; Fri, 25 Nov 2022 07:31:31 -0800 (PST) Received: from tone.k.g (lan.nucleusys.com. [92.247.61.126]) by smtp.gmail.com with ESMTPSA id p10-20020aa7cc8a000000b0045b4b67156fsm1878435edt.45.2022.11.25.07.31.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 25 Nov 2022 07:31:30 -0800 (PST) From: Petko Manolov To: linux-media@vger.kernel.org Cc: laurent.pinchart@ideasonboard.com, sakari.ailus@iki.fi, Petko Manolov Subject: [PATCH v1 3/5] media: i2c: imx492: driver's source Date: Fri, 25 Nov 2022 17:31:18 +0200 Message-Id: <20221125153120.541298-4-petko.manolov@konsulko.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221125153120.541298-1-petko.manolov@konsulko.com> References: <20221125153120.541298-1-petko.manolov@konsulko.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-LSpam-Score: -2.5 (--) X-LSpam-Report: No, score=-2.5 required=5.0 tests=BAYES_00=-1.9,DKIM_SIGNED=0.1,DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1 autolearn=ham autolearn_force=no imx492 is a diagonal 23.1 mm (Type 1.4) CMOS image sensor with color or monochrome square pixel array and approximately 47.08 M effective pixels. 12-bit digital output makes it possible to output the signals with high definition for moving pictures. It is programmable through I2C interface. The I2C client address can be either 0x10 or 0x1a depending on SLASEL pin. Image data is sent through MIPI CSI-2. Signed-off-by: Petko Manolov --- drivers/media/i2c/imx492.c | 1092 ++++++++++++++++++++++++++++++++++++ 1 file changed, 1092 insertions(+) create mode 100644 drivers/media/i2c/imx492.c diff --git a/drivers/media/i2c/imx492.c b/drivers/media/i2c/imx492.c new file mode 100644 index 000000000000..0713256b4b63 --- /dev/null +++ b/drivers/media/i2c/imx492.c @@ -0,0 +1,1092 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Sony imx492 Camera Sensor Driver (based on imx412.c source); + * + * Copyright (C) 2022 Petko Manolov + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "imx492.h" + +/* Streaming Mode */ +#define IMX492_REG_MODE_SELECT 0x3000 + +/* Chip ID */ +#define IMX492_ID 0x13 + +/* Analog gain control */ +#define IMX492_REG_AGAIN 0x300a +#define IMX492_AGAIN_MIN 0 +#define IMX492_AGAIN_MAX 978 +#define IMX492_AGAIN_STEP 1 +#define IMX492_AGAIN_DEFAULT 0 + +/* Group hold register */ +#define IMX492_REG_HOLD 0x302b +#define IMX492_REG_XMSTA 0x3033 +#define IMX492_REG_SYSCLKEN 0x35e5 + +/* CSI2 HW configuration */ +#define IMX492_LINK_FREQ 745000000 +#define IMX492_NUM_DATA_LANES 4 + +#define IMX492_REG_MIN 0x3000 +#define IMX492_REG_MAX 0xffff + +/* *** */ + +#define IMX492_REG_STANDBY IMX492_REG_MODE_SELECT +#define IMX492_BIT_STANDBY 0x01 +#define IMX492_BIT_STBLOGIC 0x02 +#define IMX492_BIT_STBDV 0x10 + +#define IMX492_MODE_STANDBY (IMX492_BIT_STBDV | IMX492_BIT_STBLOGIC | IMX492_BIT_STANDBY) +#define IMX492_MODE_STREAMING 0x00 + +#define IMX492_REG_TESTPTRN 0x303A +#define IMX492_BIT_CLKEN 0x01 +#define IMX492_BIT_TESTPTRN 0x10 +#define IMX492_BITS_TPTRN_ON (IMX492_BIT_TESTPTRN | IMX492_BIT_CLKEN) +#define IMX492_BITS_TPTRN_OFF 0x00 + +#define IMX492_REG_TESTPATSEL 0x303B +#define IMX492_BIT_TPAT00 0x00 +#define IMX492_BIT_TPAT01 0x01 +#define IMX492_BIT_TPAT02 0x02 +#define IMX492_BIT_TPAT03 0x03 +#define IMX492_BIT_TPAT0A 0x0A +#define IMX492_BIT_TPAT0B 0x0B + +#define IMX492_EXPOSURE_MIN 8 +#define IMX492_EXPOSURE_OFFSET 22 +#define IMX492_EXPOSURE_STEP 1 +#define IMX492_EXPOSURE_DEFAULT 0x0648 + +#define DEFAULT_FPS 6 + +/** + * struct imx492_reg_list - imx492 sensor register list + * @num_of_regs: Number of registers in the list + * @regs: Pointer to register list + */ +struct imx492_reg_list { + u32 num_of_regs; + const struct imx492_reg *regs; +}; + +/** + * struct imx492_mode - imx492 sensor mode structure + * @width: Frame width + * @height: Frame height + * @code: Format code + * @hblank: Horizontal blanking in lines + * @vblank: Vertical blanking in lines + * @vblank_min: Minimum vertical blanking in lines + * @vblank_max: Maximum vertical blanking in lines + * @pclk: Sensor pixel clock + * @link_freq_idx: Link frequency index + * @reg_list: Register list for sensor mode + */ +struct imx492_mode { + u32 width; + u32 height; + u32 code; + u32 hblank; + u32 hblank_min; + u32 hblank_max; + u32 vblank; + u32 vblank_min; + u32 vblank_max; + u64 pclk; + u32 link_freq_idx; + struct imx492_reg_list reg_list; +}; + +/** + * struct imx492 - imx492 sensor device structure + * @dev: Pointer to generic device + * @client: Pointer to i2c client + * @sd: V4L2 sub-device + * @pad: Media pad. Only one pad supported + * @reset_gpio: Sensor reset gpio + * @reset_gpio: Sensor power gpio + * @inclk: Sensor input clock + * @supplies: Regulator supplies + * @ctrl_handler: V4L2 control handler + * @link_freq_ctrl: Pointer to link frequency control + * @pclk_ctrl: Pointer to pixel clock control + * @hblank_ctrl: Pointer to horizontal blanking control + * @vblank_ctrl: Pointer to vertical blanking control + * @exp_ctrl: Pointer to exposure control + * @again_ctrl: Pointer to analog gain control + * @vblank: Vertical blanking in lines + * @cur_mode: Pointer to current selected sensor mode + * @mutex: Mutex for serializing sensor controls + * @streaming: Flag indicating streaming state + */ +struct imx492 { + struct device *dev; + struct i2c_client *client; + struct v4l2_subdev sd; + struct media_pad pad; + struct v4l2_captureparm scap; + struct gpio_desc *reset_gpio; + struct gpio_desc *power_gpio; + struct gpio_desc *oscen_gpio; + struct clk *inclk; + struct v4l2_ctrl_handler ctrl_handler; + struct v4l2_ctrl *link_freq_ctrl; + struct v4l2_ctrl *pclk_ctrl; + struct v4l2_ctrl *hblank_ctrl; + struct v4l2_ctrl *vblank_ctrl; + struct v4l2_ctrl *exp_ctrl; + struct v4l2_ctrl *again_ctrl; + const struct imx492_mode *cur_mode; + struct mutex mutex; + u32 tpatt; + u32 vblank; + bool streaming; +}; + +static const s64 link_freq[] = { + IMX492_LINK_FREQ, +}; + + +/* Supported sensor mode configurations */ +static const struct imx492_mode supported_modes[] = { + { + .width = 8192, + .height = 4320, + .hblank = 1108, + .hblank_min = 1102, + .hblank_max = 32768, + .vblank = 5728, + .vblank_min = 4428, + .vblank_max = 32768, + .pclk = 745000000, + .link_freq_idx = 0, + .code = MEDIA_BUS_FMT_SGBRG12_1X12, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_17to9_regs), + .regs = mode_17to9_regs, + }, + }, { + .width = 8192, + .height = 5556, + .hblank = 1108, + .hblank_min = 1102, + .hblank_max = 32768, + .vblank = 5728, + .vblank_min = 4428, + .vblank_max = 32768, + .pclk = 745000000, + .link_freq_idx = 0, + .code = MEDIA_BUS_FMT_SGBRG12_1X12, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_all_regs), + .regs = mode_all_regs, + }, + }, +}; + +static const char * const imx492_test_pattern_menu[] = { + "Disabled", + "Solid black", + "Solid white", + "Solid dark grey", + "Solid light gray", + "None", + "None", + "None", + "None", + "None", + "None", + "Vertical color bars", + "Horizontal color bars", +}; + +/** + * to_imx492() - imx492 V4L2 sub-device to imx492 device. + * @subdev: pointer to imx492 V4L2 sub-device + * + * Return: pointer to imx492 device + */ +static inline struct imx492 *to_imx492(struct v4l2_subdev *subdev) +{ + return container_of(subdev, struct imx492, sd); +} + +/** + * imx492_read_reg() - Read registers. + * @imx492: pointer to imx492 device + * @reg: register address + * @len: length of bytes to read. Max supported bytes is 4 + * @val: pointer to register value to be filled. + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_read_reg(struct imx492 *imx492, u16 reg, u32 len, u32 *val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx492->sd); + struct i2c_msg msgs[2] = {0}; + u8 addr_buf[2] = {0}; + u8 data_buf[4] = {0}; + int ret; + + if (WARN_ON(len > 4)) + return -EINVAL; + + put_unaligned_be16(reg, addr_buf); + + /* Write register address */ + msgs[0].addr = client->addr; + msgs[0].flags = 0; + msgs[0].len = ARRAY_SIZE(addr_buf); + msgs[0].buf = addr_buf; + + /* Read data from register */ + msgs[1].addr = client->addr; + msgs[1].flags = I2C_M_RD; + msgs[1].len = len; + msgs[1].buf = &data_buf[4 - len]; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) + return -EIO; + + *val = get_unaligned_be32(data_buf); + + return 0; +} + +/** + * imx492_write_reg() - Write register + * @imx492: pointer to imx492 device + * @reg: register address + * @len: length of bytes. Max supported bytes is 4 + * @val: register value + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_write_reg(struct imx492 *imx492, u16 reg, u32 len, u32 val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx492->sd); + u8 buf[6] = {0}; + + if (WARN_ON(len > 4)) + return -EINVAL; + + put_unaligned_be16(reg, buf); + put_unaligned_be32(val << (8 * (4 - len)), buf + 2); + if (i2c_master_send(client, buf, len + 2) != len + 2) + return -EIO; + + return 0; +} + +/** + * imx492_write_regs() - Write a list of registers + * @imx492: pointer to imx492 device + * @regs: list of registers to be written + * @len: length of registers array + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_write_regs(struct imx492 *imx492, + const struct imx492_reg *regs, u32 len) +{ + unsigned int i; + int ret; + + for (i = 0; i < len; i++) { + ret = imx492_write_reg(imx492, regs[i].address, 1, regs[i].val); + if (ret) + return ret; + } + + return 0; +} + +static u32 imx492_get_format_code(struct imx492 *imx492, u32 code) +{ + /* for now this is the only format we support */ + return MEDIA_BUS_FMT_SGBRG12_1X12; +} + +/** + * imx492_update_controls() - Update control ranges based on streaming mode + * @imx492: pointer to imx492 device + * @mode: pointer to imx492_mode sensor mode + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_update_controls(struct imx492 *imx492, + const struct imx492_mode *mode) +{ + int ret; + + ret = __v4l2_ctrl_s_ctrl(imx492->link_freq_ctrl, mode->link_freq_idx); + if (ret) + return ret; + + ret = __v4l2_ctrl_s_ctrl(imx492->hblank_ctrl, mode->hblank); + if (ret) + return ret; + + return __v4l2_ctrl_modify_range(imx492->vblank_ctrl, mode->vblank_min, + mode->vblank_max, 1, mode->vblank); +} + +/** + * imx492_update_exp_gain() - Set updated exposure and gain + * @imx492: pointer to imx492 device + * @exposure: updated exposure value + * @gain: updated analog gain value + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_update_exp_gain(struct imx492 *imx492, u32 exposure, u32 gain) +{ + u32 lpfr, shutter; + int ret; + + lpfr = imx492->vblank + imx492->cur_mode->height; + shutter = lpfr - exposure; + + ret = imx492_write_reg(imx492, IMX492_REG_HOLD, 1, 1); + if (ret) + return ret; + + ret = imx492_write_reg(imx492, IMX492_REG_AGAIN, 2, gain); + + return ret; +} + +/** + * imx492_set_ctrl() - Set subdevice control + * @ctrl: pointer to v4l2_ctrl structure + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct imx492 *imx492 = + container_of(ctrl->handler, struct imx492, ctrl_handler); + u32 analog_gain; + u32 exposure; + int ret; + + switch (ctrl->id) { + case V4L2_CID_VBLANK: + imx492->vblank = imx492->vblank_ctrl->val; + + ret = __v4l2_ctrl_modify_range(imx492->exp_ctrl, + IMX492_EXPOSURE_MIN, + imx492->vblank + + imx492->cur_mode->height - + IMX492_EXPOSURE_OFFSET, + 1, IMX492_EXPOSURE_DEFAULT); + break; + case V4L2_CID_EXPOSURE: + /* Set controls only if sensor is in power on state */ + if (!pm_runtime_get_if_in_use(imx492->dev)) + return 0; + exposure = ctrl->val; + analog_gain = imx492->again_ctrl->val; + ret = imx492_update_exp_gain(imx492, exposure, analog_gain); + pm_runtime_put(imx492->dev); + break; + case V4L2_CID_TEST_PATTERN: + if (ctrl->val) { + imx492_write_reg(imx492, IMX492_REG_TESTPATSEL, 1, ctrl->val - 1); + imx492_write_reg(imx492, IMX492_REG_TESTPTRN, 1, IMX492_BITS_TPTRN_ON); + } else { + imx492_write_reg(imx492, IMX492_REG_TESTPTRN, 1, IMX492_BITS_TPTRN_OFF); + } + ret = 0; + break; + default: + dev_err(imx492->dev, "Invalid control %d", ctrl->id); + ret = -EINVAL; + } + + return ret; +} + +/* V4l2 subdevice control ops*/ +static const struct v4l2_ctrl_ops imx492_ctrl_ops = { + .s_ctrl = imx492_set_ctrl, +}; + +/** + * imx492_enum_mbus_code() - Enumerate V4L2 sub-device mbus codes + * @sd: pointer to imx492 V4L2 sub-device structure + * @sd_state: V4L2 sub-device configuration + * @code: V4L2 sub-device code enumeration need to be filled + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index > ARRAY_SIZE(supported_modes)) + return -EINVAL; + + code->code = supported_modes[code->index].code; + + return 0; +} + +/** + * imx492_enum_frame_size() - Enumerate V4L2 sub-device frame sizes + * @sd: pointer to imx492 V4L2 sub-device structure + * @sd_state: V4L2 sub-device configuration + * @fsize: V4L2 sub-device size enumeration need to be filled + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_size_enum *fsize) +{ + if (fsize->index > ARRAY_SIZE(supported_modes)) + return -EINVAL; + + if (fsize->code != supported_modes[fsize->index].code) + return -EINVAL; + + fsize->max_width = supported_modes[fsize->index].width; + fsize->min_width = fsize->max_width; + fsize->max_height = supported_modes[fsize->index].height; + fsize->min_height = fsize->max_height; + + return 0; +} + +/** +n * imx492_fill_pad_format() - Fill subdevice pad format + * from selected sensor mode + * @imx492: pointer to imx492 device + * @mode: pointer to imx492_mode sensor mode + * @fmt: V4L2 sub-device format need to be filled + */ +static void imx492_fill_pad_format(struct imx492 *imx492, + const struct imx492_mode *mode, + struct v4l2_subdev_format *fmt) +{ + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.code = mode->code; + fmt->format.field = V4L2_FIELD_NONE; + fmt->format.colorspace = V4L2_COLORSPACE_RAW; + fmt->format.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + fmt->format.quantization = V4L2_QUANTIZATION_DEFAULT; + fmt->format.xfer_func = V4L2_XFER_FUNC_NONE; +} + +/** + * imx492_get_pad_format() - Get subdevice pad format + * @sd: pointer to imx492 V4L2 sub-device structure + * @sd_state: V4L2 sub-device configuration + * @fmt: V4L2 sub-device format need to be set + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_get_pad_format(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct imx492 *imx492 = to_imx492(sd); + + mutex_lock(&imx492->mutex); + + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { + struct v4l2_mbus_framefmt *framefmt; + + framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); + fmt->format = *framefmt; + } else { + imx492_fill_pad_format(imx492, imx492->cur_mode, fmt); + } + + mutex_unlock(&imx492->mutex); + + return 0; +} + +/** + * imx492_set_pad_format() - Set subdevice pad format + * @sd: pointer to imx492 V4L2 sub-device structure + * @sd_state: V4L2 sub-device configuration + * @fmt: V4L2 sub-device format need to be set + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_set_pad_format(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct imx492 *imx492 = to_imx492(sd); + const struct imx492_mode *mode; + int ret = 0; + + mutex_lock(&imx492->mutex); + + fmt->format.code = imx492_get_format_code(imx492, 0); + mode = v4l2_find_nearest_size(supported_modes, + ARRAY_SIZE(supported_modes), + width, height, + fmt->format.width, fmt->format.height); + imx492_fill_pad_format(imx492, mode, fmt); + + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { + struct v4l2_mbus_framefmt *framefmt; + + framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); + *framefmt = fmt->format; + } else { + ret = imx492_update_controls(imx492, mode); + if (!ret) + imx492->cur_mode = mode; + } + + mutex_unlock(&imx492->mutex); + + return ret; +} + +/** + * imx492_init_pad_cfg() - Initialize sub-device pad configuration + * @sd: pointer to imx492 V4L2 sub-device structure + * @sd_state: V4L2 sub-device configuration + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_init_pad_cfg(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state) +{ + struct imx492 *imx492 = to_imx492(sd); + struct v4l2_subdev_format fmt = { 0 }; + + fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; + imx492_fill_pad_format(imx492, &supported_modes[0], &fmt); + + return imx492_set_pad_format(sd, sd_state, &fmt); +} + +/** + * imx492_start_streaming() - Start sensor stream + * @imx492: pointer to imx492 device + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_start_streaming(struct imx492 *imx492) +{ + const struct imx492_reg_list *reg_list; + int ret; + + /* Write sensor mode registers */ + reg_list = &imx492->cur_mode->reg_list; + ret = imx492_write_regs(imx492, reg_list->regs, + reg_list->num_of_regs); + if (ret) { + dev_err(imx492->dev, "fail to write initial registers"); + return ret; + } + + /* Setup handler will write actual exposure and gain */ + ret = __v4l2_ctrl_handler_setup(imx492->sd.ctrl_handler); + if (ret) { + dev_err(imx492->dev, "fail to setup handler"); + return ret; + } + + /* 1st stabilization period */ + usleep_range(10000, 11000); + imx492_write_reg(imx492, IMX492_REG_MODE_SELECT, 1, 0x02); + imx492_write_reg(imx492, IMX492_REG_SYSCLKEN, 1, 0x92); + imx492_write_reg(imx492, IMX492_REG_SYSCLKEN, 1, 0x9a); + imx492_write_reg(imx492, IMX492_REG_MODE_SELECT, 1, IMX492_MODE_STREAMING); + + /* 2nd stabilization period */ + usleep_range(7000, 8000); + + /* Start streaming */ + ret = imx492_write_reg(imx492, IMX492_REG_XMSTA, 1, 0x20); + + if (ret) { + dev_err(imx492->dev, "fail to start streaming"); + return ret; + } + + return 0; +} + +/** + * imx492_stop_streaming() - Stop sensor stream + * @imx492: pointer to imx492 device + * + * Return: 0 if successful, error code otherwise. + */ +static void imx492_stop_streaming(struct imx492 *imx492) +{ + imx492_write_reg(imx492, IMX492_REG_MODE_SELECT, 1, IMX492_MODE_STANDBY); + imx492_write_reg(imx492, IMX492_REG_XMSTA, 1, 0x10); +} + +/** + * imx492_set_stream() - Enable sensor streaming + * @sd: pointer to imx492 subdevice + * @enable: set to enable sensor streaming + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_set_stream(struct v4l2_subdev *sd, int enable) +{ + struct imx492 *imx492 = to_imx492(sd); + int ret; + + mutex_lock(&imx492->mutex); + + if (imx492->streaming == enable) { + mutex_unlock(&imx492->mutex); + return 0; + } + + if (enable) { + ret = pm_runtime_resume_and_get(imx492->dev); + if (ret) + goto error_unlock; + ret = imx492_start_streaming(imx492); + if (ret) + goto error_power_off; + } else { + imx492_stop_streaming(imx492); + pm_runtime_put(imx492->dev); + } + + imx492->streaming = enable; + + mutex_unlock(&imx492->mutex); + + return 0; + +error_power_off: + pm_runtime_put(imx492->dev); +error_unlock: + mutex_unlock(&imx492->mutex); + + return ret; +} + +/** + * imx492_detect() - Detect imx492 sensor + * @imx492: pointer to imx492 device + * + * Return: 0 if successful, -EIO if sensor id does not match + */ +static int imx492_detect(struct imx492 *imx492) +{ + int ret; + u32 val; + + ret = imx492_read_reg(imx492, IMX492_REG_STANDBY, 1, &val); + if (ret) + return ret; + + if (val != IMX492_ID) { + dev_err(imx492->dev, "chip id mismatch: %x!=%x", IMX492_ID, val); + return -ENXIO; + } + + return 0; +} + +/** + * imx492_parse_hw_config() - Parse HW configuration and check if supported + * @imx492: pointer to imx492 device + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_parse_hw_config(struct imx492 *imx492) +{ + struct fwnode_handle *fwnode = dev_fwnode(imx492->dev); + struct v4l2_fwnode_endpoint bus_cfg = { + .bus_type = V4L2_MBUS_CSI2_DPHY + }; + struct fwnode_handle *ep; + unsigned int i; + int ret; + + if (!fwnode) + return -ENXIO; + + imx492->power_gpio = devm_gpiod_get(imx492->dev, "power", GPIOD_OUT_HIGH); + if (IS_ERR(imx492->power_gpio)) { + dev_err(imx492->dev, "failed to get power gpio %ld", + PTR_ERR(imx492->power_gpio)); + return PTR_ERR(imx492->power_gpio); + } + + imx492->oscen_gpio = devm_gpiod_get(imx492->dev, "oscen", GPIOD_OUT_HIGH); + if (IS_ERR(imx492->oscen_gpio)) { + dev_err(imx492->dev, "failed to get oscen gpio %ld", + PTR_ERR(imx492->oscen_gpio)); + return PTR_ERR(imx492->oscen_gpio); + } + + imx492->reset_gpio = devm_gpiod_get(imx492->dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(imx492->reset_gpio)) { + dev_err(imx492->dev, "failed to get reset gpio %ld", + PTR_ERR(imx492->reset_gpio)); + return PTR_ERR(imx492->reset_gpio); + } + + if (gpiod_direction_output(imx492->power_gpio, 1) || + gpiod_direction_output(imx492->oscen_gpio, 1) || + gpiod_direction_output(imx492->reset_gpio, 0)) { + dev_err(imx492->dev, "failed to change gpio direction"); + return -EINVAL; + } + + /* Get sensor input clock */ + imx492->inclk = devm_clk_get(imx492->dev, NULL); + if (IS_ERR(imx492->inclk)) { + dev_err(imx492->dev, "could not get inclk"); + return PTR_ERR(imx492->inclk); + } + + ep = fwnode_graph_get_next_endpoint(fwnode, NULL); + if (!ep) { + dev_err(imx492->dev, "next endpoint?"); + return -ENXIO; + } + + ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); + fwnode_handle_put(ep); + if (ret) { + dev_err(imx492->dev, "endpoint alloc parse"); + return ret; + } + + if (bus_cfg.bus.mipi_csi2.num_data_lanes != IMX492_NUM_DATA_LANES) { + dev_err(imx492->dev, "number of CSI2 data lanes %d is not supported", + bus_cfg.bus.mipi_csi2.num_data_lanes); + ret = -EINVAL; + goto done_endpoint_free; + } + + if (!bus_cfg.nr_of_link_frequencies) { + dev_err(imx492->dev, "no link frequencies defined"); + ret = -EINVAL; + goto done_endpoint_free; + } + + for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) { + if (bus_cfg.link_frequencies[i] == IMX492_LINK_FREQ) + goto done_endpoint_free; + } + + ret = -EINVAL; + +done_endpoint_free: + v4l2_fwnode_endpoint_free(&bus_cfg); + + return ret; +} + +/* V4l2 subdevice ops */ +static const struct v4l2_subdev_video_ops imx492_video_ops = { + .s_stream = imx492_set_stream, +}; + +static const struct v4l2_subdev_pad_ops imx492_pad_ops = { + .init_cfg = imx492_init_pad_cfg, + .enum_mbus_code = imx492_enum_mbus_code, + .enum_frame_size = imx492_enum_frame_size, + .get_fmt = imx492_get_pad_format, + .set_fmt = imx492_set_pad_format, +}; + +static const struct v4l2_subdev_ops imx492_subdev_ops = { + .video = &imx492_video_ops, + .pad = &imx492_pad_ops, +}; + +/** + * imx492_power_on() - Sensor power on sequence + * @dev: pointer to i2c device + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_power_on(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct imx492 *imx492 = to_imx492(sd); + + gpiod_set_value_cansleep(imx492->power_gpio, 1); + msleep(1); + gpiod_set_value_cansleep(imx492->reset_gpio, 1); + msleep(1); + gpiod_set_value_cansleep(imx492->oscen_gpio, 1); + msleep(1); + + return 0; +} + +/** + * imx492_power_off() - Sensor power off sequence + * @dev: pointer to i2c device + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_power_off(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct imx492 *imx492 = to_imx492(sd); + + gpiod_set_value_cansleep(imx492->oscen_gpio, 0); + gpiod_set_value_cansleep(imx492->reset_gpio, 0); + gpiod_set_value_cansleep(imx492->power_gpio, 0); + + return 0; +} + +/** + * imx492_init_controls() - Initialize sensor subdevice controls + * @imx492: pointer to imx492 device + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_init_controls(struct imx492 *imx492) +{ + struct v4l2_ctrl_handler *ctrl_hdlr = &imx492->ctrl_handler; + const struct imx492_mode *mode = imx492->cur_mode; + u32 lpfr; + int ret; + + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 6); + if (ret) + return ret; + + /* Serialize controls with sensor device */ + ctrl_hdlr->lock = &imx492->mutex; + /* Initialize exposure and gain */ + lpfr = mode->vblank + mode->height; + imx492->exp_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, + &imx492_ctrl_ops, + V4L2_CID_EXPOSURE, + IMX492_EXPOSURE_MIN, + lpfr - IMX492_EXPOSURE_OFFSET, + IMX492_EXPOSURE_STEP, + IMX492_EXPOSURE_DEFAULT); + + imx492->again_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, + &imx492_ctrl_ops, + V4L2_CID_ANALOGUE_GAIN, + IMX492_AGAIN_MIN, + IMX492_AGAIN_MAX, + IMX492_AGAIN_STEP, + IMX492_AGAIN_DEFAULT); + + v4l2_ctrl_cluster(2, &imx492->exp_ctrl); + + imx492->vblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, + &imx492_ctrl_ops, + V4L2_CID_VBLANK, + mode->vblank_min, + mode->vblank_max, + 1, mode->vblank); + /* Read only controls */ + imx492->hblank_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, + &imx492_ctrl_ops, + V4L2_CID_HBLANK, + mode->hblank_min, + mode->hblank_max, + 1, mode->hblank); + if (imx492->hblank_ctrl) + imx492->hblank_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + imx492->pclk_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, + &imx492_ctrl_ops, + V4L2_CID_PIXEL_RATE, + mode->pclk, mode->pclk, + 1, mode->pclk); + + imx492->link_freq_ctrl = v4l2_ctrl_new_int_menu(ctrl_hdlr, + &imx492_ctrl_ops, + V4L2_CID_LINK_FREQ, + ARRAY_SIZE(link_freq) - + 1, + mode->link_freq_idx, + link_freq); + if (imx492->link_freq_ctrl) + imx492->link_freq_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx492_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(imx492_test_pattern_menu) - 1, + 0, 0, imx492_test_pattern_menu); + + if (ctrl_hdlr->error) { + dev_err(imx492->dev, "control init failed: %d", ctrl_hdlr->error); + v4l2_ctrl_handler_free(ctrl_hdlr); + return ctrl_hdlr->error; + } + + imx492->sd.ctrl_handler = ctrl_hdlr; + + return 0; +} + +/** + * imx492_probe() - I2C client device binding + * @client: pointer to i2c client device + * + * Return: 0 if successful, error code otherwise. + */ +static int imx492_probe(struct i2c_client *client) +{ + struct imx492 *imx492; + int ret; + + imx492 = devm_kzalloc(&client->dev, sizeof(*imx492), GFP_KERNEL); + if (!imx492) + return -ENOMEM; + + imx492->dev = &client->dev; + + /* Initialize subdev */ + v4l2_i2c_subdev_init(&imx492->sd, client, &imx492_subdev_ops); + + ret = imx492_parse_hw_config(imx492); + if (ret) { + dev_err(imx492->dev, "HW configuration is not supported"); + return ret; + } + + mutex_init(&imx492->mutex); + + ret = imx492_power_on(imx492->dev); + if (ret) { + dev_err(imx492->dev, "failed to power-on the sensor"); + goto error_mutex_destroy; + } + + /* Check module identity */ + ret = imx492_detect(imx492); + if (ret) { + dev_err(imx492->dev, "failed to find sensor: %d", ret); + goto error_power_off; + } + + /* Set default mode to max resolution */ + imx492->cur_mode = &supported_modes[0]; + imx492->vblank = imx492->cur_mode->vblank; + + ret = imx492_init_controls(imx492); + if (ret) { + dev_err(imx492->dev, "failed to init controls: %d", ret); + goto error_power_off; + } + + /* Initialize subdev */ + imx492->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + imx492->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + + imx492->scap.capability = V4L2_MODE_HIGHQUALITY | V4L2_CAP_TIMEPERFRAME; + imx492->scap.capturemode = 0; + imx492->scap.timeperframe.denominator = DEFAULT_FPS; + imx492->scap.timeperframe.numerator = 1; + + /* Initialize source pad */ + imx492->pad.flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&imx492->sd.entity, 1, &imx492->pad); + if (ret) { + dev_err(imx492->dev, "failed to init entity pads: %d", ret); + goto error_handler_free; + } + + ret = v4l2_async_register_subdev(&imx492->sd); + if (ret < 0) { + dev_err(imx492->dev, "failed to register async subdev: %d", ret); + goto error_media_entity; + } + + pm_runtime_set_active(imx492->dev); + pm_runtime_enable(imx492->dev); + pm_runtime_idle(imx492->dev); + + return 0; + +error_media_entity: + media_entity_cleanup(&imx492->sd.entity); +error_handler_free: + v4l2_ctrl_handler_free(imx492->sd.ctrl_handler); +error_power_off: + imx492_power_off(imx492->dev); +error_mutex_destroy: + mutex_destroy(&imx492->mutex); + + return ret; +} + +/** + * imx492_remove() - I2C client device unbinding + * @client: pointer to I2C client device + */ +static void imx492_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct imx492 *imx492 = to_imx492(sd); + + v4l2_async_unregister_subdev(sd); + media_entity_cleanup(&sd->entity); + v4l2_ctrl_handler_free(sd->ctrl_handler); + pm_runtime_disable(&client->dev); + if (!pm_runtime_status_suspended(&client->dev)) + imx492_power_off(&client->dev); + pm_runtime_set_suspended(&client->dev); + mutex_destroy(&imx492->mutex); +} + +static const struct dev_pm_ops imx492_pm_ops = { + SET_RUNTIME_PM_OPS(imx492_power_off, imx492_power_on, NULL) +}; + +static const struct of_device_id imx492_of_match[] = { + { .compatible = "sony,imx492_mipi" }, + { } +}; + +MODULE_DEVICE_TABLE(of, imx492_of_match); + +static struct i2c_driver imx492_driver = { + .probe_new = imx492_probe, + .remove = imx492_remove, + .driver = { + .name = "imx492", + .pm = &imx492_pm_ops, + .of_match_table = imx492_of_match, + }, +}; + +module_i2c_driver(imx492_driver); + +MODULE_DESCRIPTION("Sony imx492 sensor driver"); +MODULE_AUTHOR("Petko Manolov "); +MODULE_LICENSE("GPL"); From patchwork Fri Nov 25 15:31:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petko Manolov X-Patchwork-Id: 87818 Received: from vger.kernel.org ([23.128.96.18]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1oyafx-00CzEZ-3D; Fri, 25 Nov 2022 15:31:37 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229623AbiKYPbf (ORCPT + 1 other); Fri, 25 Nov 2022 10:31:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53078 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229587AbiKYPbe (ORCPT ); Fri, 25 Nov 2022 10:31:34 -0500 Received: from mail-ej1-x630.google.com (mail-ej1-x630.google.com [IPv6:2a00:1450:4864:20::630]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 72A0A2871E for ; Fri, 25 Nov 2022 07:31:33 -0800 (PST) Received: by mail-ej1-x630.google.com with SMTP id ud5so11125105ejc.4 for ; Fri, 25 Nov 2022 07:31:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=konsulko.com; s=google; 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=nh5MwmK/rpgu4dep0zQ7hNCT5OBsH1qzr2wUQzS5UDg=; b=Z0QOUkHNbUhcxB7/qsRBOHolpcQUNhJ2Vr+k+PhgqYsMopbt5CG8AGVuNwcc9uFJbV y1kOkWvenIaa/OsBSyNyVum+v3lc/UP1yzOntuZcHirrFKLPYgp04PHgABy4N1oyVdzB RgjaYgdV0jTyXJOtCEM5Yg6Iy0kUfHAv3hb1k= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=nh5MwmK/rpgu4dep0zQ7hNCT5OBsH1qzr2wUQzS5UDg=; b=b6/HL2DEEQntOonqpmBljO01qtwvpXNJf+3gCZQ3U88ihCOoI5D+IWXYGsjzB0jTQK UGKZi1JMBkoYzQ/TeJHVY68kMSWQMI4Hdfax2FuWEhDWx4lEbfYq0He8Z2ueclfOUp9r y0+cxFN0j27wJnCkQAUPcpHv218TaKVu/NoBpLNwhCVosGYnetb8/hX7v90rCqM5Qeh0 GdMh0I3a0M7YB+BXsCapp3Al0bsVN0gos99Acg//H1YUm/PU5KA5icFQol71vdRKD83n 6H/bffaYXKzjihLPH4/i7wgyMULoIirEGsd7a6+RT7vC+t+nrLK3tSPVGiajPSb9j0v6 LPIg== X-Gm-Message-State: ANoB5pmzjc4DtpMJCjHajNt3jnlKWHr4pPdLvZFNSSu0g8FlcEpoacVD g6PXmYzwnpC25RK+/FacwHO+3VARXOmunw== X-Google-Smtp-Source: AA0mqf4OW90GcQfYttnvOEzCTft2cYBLMX4YQDa7yGPxTYzzpcK79QCgYCnoUwu5jN6M8F69y4hhWA== X-Received: by 2002:a17:907:c70a:b0:7ad:d6c6:eb7c with SMTP id ty10-20020a170907c70a00b007add6c6eb7cmr24743937ejc.249.1669390292508; Fri, 25 Nov 2022 07:31:32 -0800 (PST) Received: from tone.k.g (lan.nucleusys.com. [92.247.61.126]) by smtp.gmail.com with ESMTPSA id p10-20020aa7cc8a000000b0045b4b67156fsm1878435edt.45.2022.11.25.07.31.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 25 Nov 2022 07:31:31 -0800 (PST) From: Petko Manolov To: linux-media@vger.kernel.org Cc: laurent.pinchart@ideasonboard.com, sakari.ailus@iki.fi, Petko Manolov Subject: [PATCH v1 4/5] media: i2c: add imx492 config entry Date: Fri, 25 Nov 2022 17:31:19 +0200 Message-Id: <20221125153120.541298-5-petko.manolov@konsulko.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221125153120.541298-1-petko.manolov@konsulko.com> References: <20221125153120.541298-1-petko.manolov@konsulko.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-LSpam-Score: -2.5 (--) X-LSpam-Report: No, score=-2.5 required=5.0 tests=BAYES_00=-1.9,DKIM_SIGNED=0.1,DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1 autolearn=ham autolearn_force=no Adds the Kconfig entry right after it's sibling. Signed-off-by: Petko Manolov --- drivers/media/i2c/Kconfig | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 49c1c27afdc1..db69725d2f9a 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -228,6 +228,20 @@ config VIDEO_IMX412 To compile this driver as a module, choose M here: the module will be called imx412. +config VIDEO_IMX492 + tristate "Sony IMX492 sensor support" + depends on OF_GPIO + depends on I2C && VIDEO_DEV + select VIDEO_V4L2_SUBDEV_API + select MEDIA_CONTROLLER + select V4L2_FWNODE + help + This is a Video4Linux2 sensor driver for the Sony + IMX492 camera. + + To compile this driver as a module, choose M here: the + module will be called imx492. + config VIDEO_MAX9271_LIB tristate From patchwork Fri Nov 25 15:31:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petko Manolov X-Patchwork-Id: 87820 Received: from vger.kernel.org ([23.128.96.18]) by www.linuxtv.org with esmtp (Exim 4.92) (envelope-from ) id 1oyagG-00CzEZ-Hr; Fri, 25 Nov 2022 15:31:56 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229630AbiKYPbz (ORCPT + 1 other); Fri, 25 Nov 2022 10:31:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53170 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229580AbiKYPbx (ORCPT ); Fri, 25 Nov 2022 10:31:53 -0500 Received: from mail-ej1-x62c.google.com (mail-ej1-x62c.google.com [IPv6:2a00:1450:4864:20::62c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9288C25E8A for ; Fri, 25 Nov 2022 07:31:52 -0800 (PST) Received: by mail-ej1-x62c.google.com with SMTP id vv4so11141785ejc.2 for ; Fri, 25 Nov 2022 07:31:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=konsulko.com; s=google; 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=B7xutFDYfxv2Xy2TxGLikGVF5LOdRp8bJ3PZY3ODS4k=; b=XUPHLQeUPNtB1gOhP/tR9W79tQ1jjiAvTDwHuS2ilQDSOOymQZtrNII0uBGDV3PYWS RwWrZedwzNVCCxh4BJwV/lEHBmMyHyopIIqz1i4nzFsauP9RuPd87oTVJmGsvHf2Sjis ut43W9/yBNc6SMY7q8RfhvLSzWEX4La4n8yx0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; 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=B7xutFDYfxv2Xy2TxGLikGVF5LOdRp8bJ3PZY3ODS4k=; b=IATjhqnxV/fzS5T+dKtYGwwl9dHR6Dm0pHTAXKxL+DuoA0fJWH2rYPLyRdmkK7baNi Ezr37ojA2DcI6H94Wa1QAUDAP70WZs/sNiiauhj3YLrM2jLkYL2j3T4RDKUmN9svtQkQ 9GFF1mp6xjEL+O+EsPbntCigx9R7sA7538yVyaAwEr6UIMFhz8b3RYtWSAA9/5WhONjK j3Xtxj6UtlrAGkod4enHlmjBadCNAy9QLZp+hLu4hLRW8zpW5yGAmsh1opKVI6a9AIy9 Ii0nx6VRMsf9DRNB83SwBewDObbcnltVSS+0SAx9EF+MqDzrgx0BWp36gzLQKbrvoWCy DSfg== X-Gm-Message-State: ANoB5pnVaWLcq9wtE5Lfv1vuZyONvLfbvyTYFwUpZuwcfDuVnjMAj7mo KmvavVrpD85/SOtQnPz5UXqKJXDSt7ywmQ== X-Google-Smtp-Source: AA0mqf5ffyFmityByOs/JOCceWPfZw+kQuNw1EgBj+gAbhyZV3Zexcz82scNQqjBm9zmN9TJ+K6rSg== X-Received: by 2002:a17:906:cf85:b0:78d:b66d:749f with SMTP id um5-20020a170906cf8500b0078db66d749fmr31106432ejb.566.1669390293850; Fri, 25 Nov 2022 07:31:33 -0800 (PST) Received: from tone.k.g (lan.nucleusys.com. [92.247.61.126]) by smtp.gmail.com with ESMTPSA id p10-20020aa7cc8a000000b0045b4b67156fsm1878435edt.45.2022.11.25.07.31.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 25 Nov 2022 07:31:33 -0800 (PST) From: Petko Manolov To: linux-media@vger.kernel.org Cc: laurent.pinchart@ideasonboard.com, sakari.ailus@iki.fi, Petko Manolov Subject: [PATCH v1 5/5] media: i2c: add imx492 entry for make Date: Fri, 25 Nov 2022 17:31:20 +0200 Message-Id: <20221125153120.541298-6-petko.manolov@konsulko.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20221125153120.541298-1-petko.manolov@konsulko.com> References: <20221125153120.541298-1-petko.manolov@konsulko.com> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-LSpam-Score: -2.5 (--) X-LSpam-Report: No, score=-2.5 required=5.0 tests=BAYES_00=-1.9,DKIM_SIGNED=0.1,DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,HEADER_FROM_DIFFERENT_DOMAINS=0.5,MAILING_LIST_MULTI=-1 autolearn=ham autolearn_force=no Make sure the driver gets compiled in case it is selected in Kconfig. Signed-off-by: Petko Manolov --- drivers/media/i2c/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index ba28a8f8a07f..8cdad7e25e5e 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_VIDEO_IMX334) += imx334.o obj-$(CONFIG_VIDEO_IMX335) += imx335.o obj-$(CONFIG_VIDEO_IMX355) += imx355.o obj-$(CONFIG_VIDEO_IMX412) += imx412.o +obj-$(CONFIG_VIDEO_IMX492) += imx492.o obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o obj-$(CONFIG_VIDEO_ISL7998X) += isl7998x.o obj-$(CONFIG_VIDEO_KS0127) += ks0127.o