From nobody Mon Feb 9 04:45:32 2026 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5ABEA29ACE5 for ; Fri, 7 Nov 2025 13:03:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762520599; cv=none; b=pz0pmDccUtU8KW9zdsrzgpSZTxB0mWsYsDWLWEh3nL1BaNkFklwyaZxUGZ6TqHm4kvhhU5EfUw+9Jkv598mURtCbYD3pAoCLy2s9BGRHzXTAzBywhVWPsLKaVku8S5a0UcEpzuMrRXMTgAnnX+pzsyejyyS0Agyz+cQ5vEGMLYo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762520599; c=relaxed/simple; bh=gaAkl13+hLTaTFl4XxH8wVSJLs+i2Xf9TdiN3O4IE9g=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=X6LOu3AR21xyXMDEXrsde68mlp3fcKn5R21aGZaW76wSvqZ6l9sohE+9G5H+TSeklfKXqZmYu7BbbCG61IfAZ0qZRp/N9phZeZ3Hb4Cgw34Zap0rTgYq/b4SJhLplYsGHfPTow7unPQzRbOng5WxJxyQqBg3CRPLUsbsU6LjVwA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=KuLzNU32; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=hda3PcoI; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="KuLzNU32"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="hda3PcoI" Received: from pps.filterd (m0279869.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 5A7B56da3174700 for ; Fri, 7 Nov 2025 13:03:16 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= G40SlKpdS7e4bW3M9vZNvOUg9wFUDrREVO2yeCjm1Ic=; b=KuLzNU32VFXX3PL/ Ly7KFKRWsRRyLpP96a5isxEzitSNgTn5+T30TrrEwtIQib4Eeh4UGzXneti/Cv58 ldMRMgT3Sw6BUmajVsmqgCth+M1q/sAYuqLh/soLPAK65vwH7G53GgLL/Z6YTZC3 9iB/f777v+mjf51rXsrb2lSaJ3qNF3irGl96B/XwySGlbOpQxADN6jmo6W6FyoTG FfHIhyb66k5D3+IxyxFXn3yayLydpdWRlhJSl1X+8XU6rpgnydLF8M2uJonRjI9I ajux0KUL1zv03p9C+Q3M6nd45WJY5JV2yrDvKDK1lYSNLUZ2N/hW/gOb5j35JCGO tWtFFg== Received: from mail-pl1-f198.google.com (mail-pl1-f198.google.com [209.85.214.198]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4a9fk8099t-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Fri, 07 Nov 2025 13:03:16 +0000 (GMT) Received: by mail-pl1-f198.google.com with SMTP id d9443c01a7336-29085106b99so14547685ad.1 for ; Fri, 07 Nov 2025 05:03:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1762520595; x=1763125395; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=G40SlKpdS7e4bW3M9vZNvOUg9wFUDrREVO2yeCjm1Ic=; b=hda3PcoIPY4myvZQXIrOpqzb6wqiyFn+IbmZqKWgRLKdpsCRaRggkqDzoOcETk6G6+ NTrXtqRCFEwRHcGBNMuOXwGIB9gttiGezWVsP2oJQooTHXqh26CRfgwP0K2RrUKfaggx ibDWs+FNnyOGOpBZrHRI+xCrc4vkA0i5kq45nsFOA6yhhrbTladl3BDJn+hBQhRJRdYJ DZxMAwKl1RjF7S0seINLty2x26meYWu0eDzka67MqlJArhaLtTkKWaD0S2l4MT2QVOY8 zPdld8uueT2v56tA36G4jW0djdkuri2y6gJwyvF0jHRXrib0NMZYmudIgBvqPlzucTHm z0wg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762520595; x=1763125395; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=G40SlKpdS7e4bW3M9vZNvOUg9wFUDrREVO2yeCjm1Ic=; b=qS1KMQ0tjzMVMOnRFA6ObTzNWGR0IIj7b4GhPPYzoknLBRuqAwDkJdjViAnbUCm71G mGr+AImWsAcXIxnvzzcQMfdFWxNbbxqOi+6dJ7SDfvqXAqUQEYjfB+UMaoAjAGmlrXJH PadtWHUDGUyoPoePLyPESGv9PvHSK7g+sbur1NlNlf03PMVhpzaf+kNyWS0dpykK6VjV VwXWzUYSoWcnJTCGENJDipYxah7j25CFT1be4NxocTIN4K2Z/tFqHh5kFivgF1cjSJfI 8UJYYNUcjlvIxX5WALXOkScvrE9dFp7gOQXc8YyRfdCeousQZsPi7MBZw7z8QV6zI0NC MDIg== X-Forwarded-Encrypted: i=1; AJvYcCXSJ+lsPXqaM7PG7bdT9SpYGcGOVJl3sSw0xGXh5Q/Vw/jJV/8hiytFkldFPqBc6hON3/qjSHdD94uFc5E=@vger.kernel.org X-Gm-Message-State: AOJu0YzGLcu1HN11c/mO2zKxmtNXF7CEXc+rzN+y/ZEFKxzAPRwHl9Xa bi6tHAu5ny5I2k018eC1C/3c6zSL61Apc+7FWKqtxdBt+RhaYa9by8OVQzLfBQr8Makt0/Y3zHq ugt3HAFz3pwJIj8g8BJhVWTUUKR06peTwQqRYYPIz0R3rz+sTS0J01kWtOywwkqytsA== X-Gm-Gg: ASbGncuhFPxIWxQkm+33O6L6Xp7HKic8l/W2Cs0EnKYYT3irirORocMAkR2eH1zFnWL WHphWFpyYa5Z0n53c3RPk0WE9r0oggHdxpkQlEE0PFwJNaFWPEXpDPL7hq4Q6rZp6njWXhcnt6g PPUKhu7jZqJWC6yBaaPdtzD/nKBLhitA8IZteb8UrW6ej5/6s/3T2I/7G8MqtGqtq4a9ng5Pdh8 hqbeRQVvFiOULO3WbZrQnyiwezKFGIfDDT/sMI8+4WvyxiA1s+AuxqkxCz4rA3or8foXxkB61ho jLYlUVgZicwoVPYia2aqjglQZ51T+ak5RzyB+mm8ixDkiYBGAhqUEL9DFjtnMAhxWEw2CrzocIQ 6RL3z9VzZbuh5VjREAz78Cccr X-Received: by 2002:a17:903:384f:b0:28d:18d3:46cb with SMTP id d9443c01a7336-297c03d8fcbmr44202315ad.20.1762520595194; Fri, 07 Nov 2025 05:03:15 -0800 (PST) X-Google-Smtp-Source: AGHT+IF1NShUF3UtYHtrjbPiVmio0Nnbx07gYYOUbClFgiyLSaZbhV+891/JDNA6u3MCcjSBxwtjDw== X-Received: by 2002:a17:903:384f:b0:28d:18d3:46cb with SMTP id d9443c01a7336-297c03d8fcbmr44201605ad.20.1762520594431; Fri, 07 Nov 2025 05:03:14 -0800 (PST) Received: from hu-nlaad-hyd.qualcomm.com ([202.46.22.19]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-296509680e5sm62477745ad.1.2025.11.07.05.03.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Nov 2025 05:03:13 -0800 (PST) From: Nilesh Laad Date: Fri, 07 Nov 2025 18:32:58 +0530 Subject: [PATCH v2 1/2] dt-bindings: bridge: lt9211c: Add bindings Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251107-add-lt9211c-bridge-v2-1-b0616e23407c@oss.qualcomm.com> References: <20251107-add-lt9211c-bridge-v2-0-b0616e23407c@oss.qualcomm.com> In-Reply-To: <20251107-add-lt9211c-bridge-v2-0-b0616e23407c@oss.qualcomm.com> To: Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Marek Vasut Cc: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Nilesh Laad , venkata.valluru@oss.qualcomm.com, jessica.zhang@oss.qualcomm.com, Yi Zhang X-Mailer: b4 0.15-dev-a9b2a X-Developer-Signature: v=1; a=ed25519-sha256; t=1762520582; l=3387; i=nilesh.laad@oss.qualcomm.com; s=20250718; h=from:subject:message-id; bh=Cc83NWmW1/dAnYephO+V19Kl2afDLNqD9vMBq15QmpU=; b=xZrZ3hN+em7gs+lxlTPFVBXdsZC4IcKxjtImY2IMxTEIRL62qrDH8Z8INVgQpZxriJ4DSXywX oh1E1F9PH+QCQzv7eUv6jv5t3h/E8gq1HgY99ZjjtuxrMy2iSMe0I8h X-Developer-Key: i=nilesh.laad@oss.qualcomm.com; a=ed25519; pk=MjLHvGipC16awutyYh0FnLpT1nPxL/Cs1dCevHMrrD4= X-Proofpoint-ORIG-GUID: fzsYWDd-YxqCVFMA7ZPBAs7xlEPmxotZ X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMTA3MDEwNiBTYWx0ZWRfX6yJTbP2Kj3B5 Agj7l7pQacP6ZpUB9j1PMQQK6QxUqEQU7DzoRTqczrADVPeWDIKIkjjqSYgSJRIwpIh/FnCvEm9 TYWIStBLV366vms1NJx7Mcmcf5h0k1Sp4QqS7t9lhj11sTf52PjOEkoCYx6nEmm5dK2pkeAC913 IgGpJ49SyiUHetvmzDmmtIy+zyu4etUQXgDQTAAIZMbP5PPsDMnxV7zsPRSsA53rYWJILLtLv9S TQzegaYnfslLhC+q2VqIx9Bb4Jz848OKN/OVNsc7d5c8birFiIcIfl3SZgQSonuX9FDD9O7URU3 MaVg0S/HNFSfdrIuNOfbO2ycBvD0Atm5gZkAU/5ANKmI+eEbcGJy7bXeZMOkSfzUrRRLxTkzghA Jl/0VBZgEtuEj3Ji+BHo/hjkHKKlgw== X-Proofpoint-GUID: fzsYWDd-YxqCVFMA7ZPBAs7xlEPmxotZ X-Authority-Analysis: v=2.4 cv=CPAnnBrD c=1 sm=1 tr=0 ts=690dee14 cx=c_pps a=MTSHoo12Qbhz2p7MsH1ifg==:117 a=fChuTYTh2wq5r3m49p7fHw==:17 a=IkcTkHD0fZMA:10 a=6UeiqGixMTsA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=gEfo2CItAAAA:8 a=EUspDBNiAAAA:8 a=Xc6W96i5Xe6cDM1WBtQA:9 a=QEXdDO2ut3YA:10 a=GvdueXVYPmCkWapjIL-Q:22 a=sptkURWiP4Gy88Gu7hUp:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.100.49 definitions=2025-11-07_03,2025-11-06_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 clxscore=1011 malwarescore=0 suspectscore=0 phishscore=0 priorityscore=1501 adultscore=0 lowpriorityscore=0 impostorscore=0 bulkscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2510240001 definitions=main-2511070106 From: Yi Zhang Add bindings for lt9211c. Signed-off-by: Yi Zhang Signed-off-by: Nilesh Laad --- .../bindings/display/bridge/lontium,lt9211c.yaml | 113 +++++++++++++++++= ++++ 1 file changed, 113 insertions(+) diff --git a/Documentation/devicetree/bindings/display/bridge/lontium,lt921= 1c.yaml b/Documentation/devicetree/bindings/display/bridge/lontium,lt9211c.= yaml new file mode 100644 index 000000000000..619f718618d6 --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/lontium,lt9211c.yaml @@ -0,0 +1,113 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/bridge/lontium,lt9211c.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Lontium LT9211C DSI/LVDS/DPI to DSI/LVDS/DPI bridge. + +maintainers: + - Marek Vasut + +description: | + The LT9211C are bridge devices which convert Single/Dual-Link DSI/LVDS + or Single DPI to Single/Dual-Link DSI/LVDS or Single DPI. + +properties: + compatible: + enum: + - lontium,lt9211c + + reg: + maxItems: 1 + + reset-gpios: + maxItems: 1 + description: GPIO connected to active high RESET pin. + + vccio-supply: + description: Regulator for 1.8V IO power. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: + Primary MIPI DSI port-1 for MIPI input or + LVDS port-1 for LVDS input or DPI input. + + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: + Additional MIPI port-2 for MIPI input or LVDS port-2 + for LVDS input. Used in combination with primary + port-1 to drive higher resolution displays + + port@2: + $ref: /schemas/graph.yaml#/properties/port + description: + Primary MIPI DSI port-1 for MIPI output or + LVDS port-1 for LVDS output or DPI output. + + port@3: + $ref: /schemas/graph.yaml#/properties/port + description: + Additional MIPI port-2 for MIPI output or LVDS port-2 + for LVDS output. Used in combination with primary + port-1 to drive higher resolution displays. + + required: + - port@0 + - port@2 + +required: + - compatible + - reg + - vccio-supply + - ports + +additionalProperties: false + +examples: + - | + #include + #include + + i2c { + #address-cells =3D <1>; + #size-cells =3D <0>; + + lvds-bridge@3b { + compatible =3D "lontium,lt9211c"; + reg =3D <0x3b>; + + reset-gpios =3D <&tlmm 128 GPIO_ACTIVE_HIGH>; + + vccio-supply =3D <<9211c_1v8>; + + ports { + #address-cells =3D <1>; + #size-cells =3D <0>; + + port@0 { + reg =3D <0>; + + endpoint { + remote-endpoint =3D <&dsi0_out>; + }; + }; + + port@2 { + reg =3D <2>; + + endpoint { + remote-endpoint =3D <&panel_in_lvds>; + }; + }; + }; + }; + }; + +... --=20 2.50.1 From nobody Mon Feb 9 04:45:32 2026 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8064828980E for ; Fri, 7 Nov 2025 13:03:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762520607; cv=none; b=IDetnOaSOrVKar0ftp+sKzE2dJ8GN/Mmb62dFoa0qHnspXEKyBLq13SwmalWyidLTQjNmV9M4K4XadkiPBtc2x80+IjoMr3Km9u4b/6UEUndVs2pRlg0+7XtP6+WgPGBeDPvckubZf5J+ZGj/oXbYK2ez8+EEZsDMPZMzsuBgWA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762520607; c=relaxed/simple; bh=h5tDDDHKKRdXonkXZ6wfzSM7kv6Zc9KSO7OlOflSHms=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=R6uPrCL/m2jIMPw/Sqbc8VZCpRNknIENXTLZSuhbliHeKp8sePh9BtV0CD3GMuEOfKceIVJ7W8kDWYGY8wMukz1gKV0EAZjksRhG1vfUmU1Kj3vB6CCejS/fuQDSKdlPhOK05S95NyMBZxWO8706s3ZTRopWg+3KRCZg1BxOPJ0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=f41JShHa; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=JhNqyIK0; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="f41JShHa"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="JhNqyIK0" Received: from pps.filterd (m0279870.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 5A7B2c8M3041312 for ; Fri, 7 Nov 2025 13:03:23 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= nmQKqYX/BwMb/I9AGEv9KrUWa7xl20hwn/9xFZPYPYs=; b=f41JShHaPFXcbpWL NUll5VGaMUC2fj8D1J1p9k2GJYcNog6KWqQEgHqmh1Yk4S8C32VuQ30tmPmfuiYs T9BlTtrX1gO3Hq4E00kv+arHdiQ9Dw9ISSNfmGEcTk0ye5pzkiyU4srHM2NVrMqv M7hXYH9aUwuvoZYOnwGaToMCH/ESoi8wEO/RgCK0HP2BCReFJP85rQVOlHZqgWyt 8cUwWiVtNvn+I2rNcTd7/PstGYvSvM+AcwPV//T/jGIwtxkNd3Vq1s5oAcYX3LoZ cK1/Tj2gTpLBIBgIznbn4p0ePxiAtZGtFUP3hlxgtpjLAb4f1bbhj6ogb2LhtMrT 6gq2rQ== Received: from mail-pl1-f197.google.com (mail-pl1-f197.google.com [209.85.214.197]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4a9fj089k2-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Fri, 07 Nov 2025 13:03:23 +0000 (GMT) Received: by mail-pl1-f197.google.com with SMTP id d9443c01a7336-2955f0b8895so9593475ad.0 for ; Fri, 07 Nov 2025 05:03:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1762520602; x=1763125402; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=nmQKqYX/BwMb/I9AGEv9KrUWa7xl20hwn/9xFZPYPYs=; b=JhNqyIK0SoXjkS8SAa+dYtIocO7XW5aoT9rWEIZdo4RA6/58Us9dwHj6bnD0O6aeWr pRloX1EiCT4fkzsyDh6LCho4IqKHqaWLk4VBIDioqjgionJuyDyTbxyONuBZMrnL5t1+ yckzk2p8dHtBkASVVA0JQphESsTFXatgVnjWmofqkmBvcPOQp5J/inJgoaYXmmRuw1jv QesJfyKfuTecwwLCmup5dZ39Y38iWUnzASeuTym62lzuPI94RDuFLIQFt35Wzd9RFBqs FDzgFiIVIN5QlN0aC8mtBvUTeX8vIb19bP4gjI0x11goFDtq7fiIdjPH0nWCmOaq3RyY s31w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762520602; x=1763125402; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=nmQKqYX/BwMb/I9AGEv9KrUWa7xl20hwn/9xFZPYPYs=; b=GqFrQFDhWQg6KGHsjMhkeHWZbOZbQPYmoNuCdmgabV294Z5ulW4qL1ISjwRbTGsiXj UHFn1wA5XJO5Zn59FTOYNT/k406n5gg3Sb0Q8IvLQ/qFKyyiMaGsb6i22E8tYTEANMZQ ZjMSUtxLFXf9RxtX3LeH8A7l4zsAl41Hn/hXN0naXExiXPlgcH7j8cMiYzBIDmYoUAK9 33OwplSbnxDsqtEMlUHaBmN+YArfOzOYhjIJEdH+pZcoZi9nmWLn/L4ETiJmGJxR7FBy mqcCjqV9Kif0xEGiiRwJvcD3yoIzy2BD01HlA6War/pW6KDuc/pL4IvZ504gQWiEsmdN 9Gag== X-Forwarded-Encrypted: i=1; AJvYcCWUzQYWGHipEr1qPB2P464oMwTFdK1H9b1tEDkZrWgfL9Ynss+nodxO6v9/gXYYIK2PILLZXT/KhSw6jkU=@vger.kernel.org X-Gm-Message-State: AOJu0YxVoKQy/6CAjgfmMlX1Vqmk59VoMJtBt/xcfyxoTNTgFLLjKHgh aUbbJTPfWVF428zeTz7nclpgR0mRN5bxt/8JprDYgN6vbjNMGf9+MqpjR1y583ygbbE2n3ltpUW 4Q48tPOPVYlgz3sAG/DId4H+u8kH2wHSSsA6QqfBpzj0UHnm2Em+m86tGcyu770phpXat6RKC4Q == X-Gm-Gg: ASbGncuqjEFjq05ZR07rNLNe6TB3FGcQOamT1nok8KVOf6C2NnN3K/WVs9dgB6lK4Ly 21YsQW+CUoRI+ykhxwMn9bMJbciOxlvWCDUjevBy7kK+2W2SFSvAGQ/VzjMOIl06hyws5ETqMcM aOUpTclr+VMHmPwsklRnPtRmlJCJeiO5qi4R4NmP1+SmgQdOkSraS1ni7bFUDd3Q5FQRnv/7kT5 kKP62CDTU1nFuim0SWBciG4z6OoKNGOhm3Vn31qum5A27ZVg5gk22dOlvBIud4qYboSHptQ8AIE J6oxu6PbeqgjDKV5GIChp2JZ1uqKXOeW+X0gQ3eC+Ve4nd33rxkwz1NE3MQT5UvCTh34ytbrTj9 yd8bEWJxcQsZlpCMsIQxY//+f X-Received: by 2002:a17:902:eb83:b0:294:fc77:f041 with SMTP id d9443c01a7336-297c958e8fdmr18635855ad.25.1762520601486; Fri, 07 Nov 2025 05:03:21 -0800 (PST) X-Google-Smtp-Source: AGHT+IHsYk3QoYYymW6cVGz/o3OxSmL9uKzLMpHjN31XBtBeTlWfUuX/b+FajG/ajc4j/ihnWYE6Kg== X-Received: by 2002:a17:902:eb83:b0:294:fc77:f041 with SMTP id d9443c01a7336-297c958e8fdmr18635195ad.25.1762520600700; Fri, 07 Nov 2025 05:03:20 -0800 (PST) Received: from hu-nlaad-hyd.qualcomm.com ([202.46.22.19]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-296509680e5sm62477745ad.1.2025.11.07.05.03.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Nov 2025 05:03:20 -0800 (PST) From: Nilesh Laad Date: Fri, 07 Nov 2025 18:32:59 +0530 Subject: [PATCH v2 2/2] drm/bridge: add support for lontium lt9211c bridge Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251107-add-lt9211c-bridge-v2-2-b0616e23407c@oss.qualcomm.com> References: <20251107-add-lt9211c-bridge-v2-0-b0616e23407c@oss.qualcomm.com> In-Reply-To: <20251107-add-lt9211c-bridge-v2-0-b0616e23407c@oss.qualcomm.com> To: Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Marek Vasut Cc: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Nilesh Laad , venkata.valluru@oss.qualcomm.com, jessica.zhang@oss.qualcomm.com, Yi Zhang , Gopi Botlagunta X-Mailer: b4 0.15-dev-a9b2a X-Developer-Signature: v=1; a=ed25519-sha256; t=1762520582; l=31255; i=nilesh.laad@oss.qualcomm.com; s=20250718; h=from:subject:message-id; bh=FkBY0/1w0FgYlnixcQw0rRMPX+WVYoYYfwxVfCbyawk=; b=tTHvCjBIpUfbsUTRi8+YQx5bDkFW4N1PqbQY7vpuOZqLjWGuuLH/sgK2xkMso6qhS7xihPK86 l6tZXqDhUhXA5W/vN5aaEi1fRwFl65PyWDdGTOODqsf0VrOUOkzEulr X-Developer-Key: i=nilesh.laad@oss.qualcomm.com; a=ed25519; pk=MjLHvGipC16awutyYh0FnLpT1nPxL/Cs1dCevHMrrD4= X-Authority-Analysis: v=2.4 cv=XZyEDY55 c=1 sm=1 tr=0 ts=690dee1b cx=c_pps a=cmESyDAEBpBGqyK7t0alAg==:117 a=fChuTYTh2wq5r3m49p7fHw==:17 a=IkcTkHD0fZMA:10 a=6UeiqGixMTsA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=EUspDBNiAAAA:8 a=8QlUORy2qNFl4_zbHzYA:9 a=QEXdDO2ut3YA:10 a=1OuFwYUASf3TG4hYMiVC:22 X-Proofpoint-ORIG-GUID: n2AijC7lXnjqRhESI9qUSAHFHTe1pStP X-Proofpoint-GUID: n2AijC7lXnjqRhESI9qUSAHFHTe1pStP X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMTA3MDEwNiBTYWx0ZWRfX5Oz43yTLXTWI pNTxC3EHdM8hW2KbATWmUvnMt2+CqI0TDUfNLa+Oqg1SqMl1YDNEBc43m6tW0SkwwT559iAtrnB UY23corhbxok2eyumEhj5w12qBXRi8tXn7oRTMoYhByO0itoHz3x8c7+NeuqGsnXw9Nipn1Fvly 3TuFZPGwKrBxUqV9icED0bONXO27hifhDDYjiCDq9xfe68KzbJ3NsFfLKtY0pyXPnuz1bHuR1j3 JuYBVC5b4C7B4Vq9FAM/9B2kmZPUJWCZzQNliHiY1+IWP2N6twWECq+aFMU2Xij1tLyhcZtKCz+ lgLB5mu9ApxzVzCH6drqPqohI14Ib/6nwCvCPTblNPBQiIS2EZlQKSKcvOqTY+QTIkYKLGMqLQN IRFWvAWpmTY2gccool6RmW/COtnsAw== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.100.49 definitions=2025-11-07_03,2025-11-06_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 adultscore=0 priorityscore=1501 spamscore=0 impostorscore=0 lowpriorityscore=0 suspectscore=0 malwarescore=0 phishscore=0 bulkscore=0 clxscore=1015 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2510240001 definitions=main-2511070106 From: Yi Zhang LT9211c is a Single/Dual-Link DSI/LVDS or Single DPI input to Single-link/Dual-Link DSI/LVDS or Single DPI output bridge chip. Add support for DSI to LVDS bridge configuration. Signed-off-by: Yi Zhang Signed-off-by: Gopi Botlagunta Signed-off-by: Nilesh Laad --- drivers/gpu/drm/bridge/Kconfig | 13 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/lontium-lt9211c.c | 1106 ++++++++++++++++++++++++++= ++++ 3 files changed, 1120 insertions(+) diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index a250afd8d662..d07f426b1096 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -154,6 +154,19 @@ config DRM_LONTIUM_LT9211 chip. Please say Y if you have such hardware. =20 +config DRM_LONTIUM_LT9211C + tristate "Lontium LT9211C DSI/LVDS/DPI bridge" + depends on OF + select DRM_PANEL_BRIDGE + select DRM_KMS_HELPER + select DRM_MIPI_DSI + select REGMAP_I2C + help + Driver for Lontium LT9211C Single/Dual-Link DSI/LVDS or Single DPI + input to Single-link/Dual-Link DSI/LVDS or Single DPI output bridge + chip. + Please say Y if you have such hardware. + config DRM_LONTIUM_LT9611 tristate "Lontium LT9611 DSI/HDMI bridge" select SND_SOC_HDMI_CODEC if SND_SOC diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makef= ile index c7dc03182e59..b74d54f1a395 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_DRM_ITE_IT6263) +=3D ite-it6263.o obj-$(CONFIG_DRM_ITE_IT6505) +=3D ite-it6505.o obj-$(CONFIG_DRM_LONTIUM_LT8912B) +=3D lontium-lt8912b.o obj-$(CONFIG_DRM_LONTIUM_LT9211) +=3D lontium-lt9211.o +obj-$(CONFIG_DRM_LONTIUM_LT9211C) +=3D lontium-lt9211c.o obj-$(CONFIG_DRM_LONTIUM_LT9611) +=3D lontium-lt9611.o obj-$(CONFIG_DRM_LONTIUM_LT9611UXC) +=3D lontium-lt9611uxc.o obj-$(CONFIG_DRM_LVDS_CODEC) +=3D lvds-codec.o diff --git a/drivers/gpu/drm/bridge/lontium-lt9211c.c b/drivers/gpu/drm/bri= dge/lontium-lt9211c.c new file mode 100644 index 000000000000..bb04acefe715 --- /dev/null +++ b/drivers/gpu/drm/bridge/lontium-lt9211c.c @@ -0,0 +1,1106 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define REG_PAGE_CONTROL 0xff +#define REG_CHIPID0 0x8100 +#define REG_CHIPID0_VALUE 0x21 +#define REG_CHIPID1 0x8101 +#define REG_CHIPID1_VALUE 0x03 +#define REG_CHIPID2 0x8102 +#define REG_CHIPID2_VALUE 0xe1 + +#define REG_DSI_LANE 0xd000 +/* DSI lane count - 0 means 4 lanes ; 1, 2, 3 means 1, 2, 3 lanes. */ +#define REG_DSI_LANE_COUNT(n) ((n) & 3) + +struct lt9211c { + struct drm_bridge bridge; + struct device *dev; + struct regmap *regmap; + struct mipi_dsi_device *dsi; + struct drm_bridge *panel_bridge; + struct gpio_desc *reset_gpio; + struct regulator *vccio; + bool lvds_dual_link; + bool lvds_dual_link_even_odd_swap; + struct workqueue_struct *wq; + struct delayed_work lt9211c_dw; + struct drm_display_mode mode; + bool bpp24; + bool jeida; + bool de; +}; + +static const struct regmap_range lt9211c_rw_ranges[] =3D { + regmap_reg_range(0xff, 0xff), + regmap_reg_range(0x8100, 0x8182), + regmap_reg_range(0x8200, 0x82aa), + regmap_reg_range(0x8500, 0x85ff), + regmap_reg_range(0x8600, 0x86a0), + regmap_reg_range(0x8700, 0x8746), + regmap_reg_range(0xd000, 0xd0a7), + regmap_reg_range(0xd400, 0xd42c), + regmap_reg_range(0xd800, 0xd838), + regmap_reg_range(0xd9c0, 0xd9d5), +}; + +static const struct regmap_access_table lt9211c_rw_table =3D { + .yes_ranges =3D lt9211c_rw_ranges, + .n_yes_ranges =3D ARRAY_SIZE(lt9211c_rw_ranges), +}; + +static const struct regmap_range_cfg lt9211c_range =3D { + .name =3D "lt9211c", + .range_min =3D 0x0000, + .range_max =3D 0xda00, + .selector_reg =3D REG_PAGE_CONTROL, + .selector_mask =3D 0xff, + .selector_shift =3D 0, + .window_start =3D 0, + .window_len =3D 0x100, +}; + +static const struct regmap_config lt9211c_regmap_config =3D { + .reg_bits =3D 8, + .val_bits =3D 8, + .rd_table =3D <9211c_rw_table, + .wr_table =3D <9211c_rw_table, + .volatile_table =3D <9211c_rw_table, + .ranges =3D <9211c_range, + .num_ranges =3D 1, + .cache_type =3D REGCACHE_RBTREE, + .max_register =3D 0xda00, +}; + +static struct lt9211c *bridge_to_lt9211c(struct drm_bridge *bridge) +{ + return container_of(bridge, struct lt9211c, bridge); +} + +static int lt9211c_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct lt9211c *ctx =3D bridge_to_lt9211c(bridge); + + return drm_bridge_attach(bridge->encoder, ctx->panel_bridge, + &ctx->bridge, flags); +} + +static int lt9211c_read_chipid(struct lt9211c *ctx) +{ + u8 chipid[3]; + int ret; + + /* Read Chip ID registers and verify the chip can communicate. */ + ret =3D regmap_bulk_read(ctx->regmap, REG_CHIPID0, chipid, 3); + if (ret < 0) { + dev_err(ctx->dev, "Failed to read Chip ID: %d\n", ret); + return ret; + } + + /* Test for known Chip ID. */ + if (chipid[0] !=3D REG_CHIPID0_VALUE || chipid[1] !=3D REG_CHIPID1_VALUE = || + chipid[2] !=3D REG_CHIPID2_VALUE) { + dev_err(ctx->dev, "Unknown Chip ID: 0x%02x 0x%02x 0x%02x\n", + chipid[0], chipid[1], chipid[2]); + return -EINVAL; + } + + return 0; +} + +static int lt9211c_configure_rx(struct lt9211c *ctx) +{ + unsigned int pval; + + const struct reg_sequence lt9211c_rx_phy_seq[] =3D { + { REG_DSI_LANE, REG_DSI_LANE_COUNT(ctx->dsi->lanes) }, + { 0x8201, 0x11 }, + { 0x8218, 0x48 }, + { 0x8201, 0x91 }, + { 0x8202, 0x00 }, + { 0x8203, 0xee }, + { 0x8209, 0x21 }, + { 0x8204, 0x44 }, + { 0x8205, 0xc4 }, + { 0x8206, 0x44 }, + { 0x8213, 0x0c }, + + { 0xd001, 0x00 }, + { 0xd002, 0x0e }, + { 0xd005, 0x00 }, + { 0xd00a, 0x59 }, + { 0xd00b, 0x20 }, + }; + + const struct reg_sequence lt9211c_rx_phy_reset_seq[] =3D { + { 0x8109, 0xde }, + { 0x8109, 0xdf }, + }; + + const struct reg_sequence lt9211c_rx_clk_sel_seq[] =3D { + { 0x85e9, 0x88 }, + { 0x8180, 0x51 }, + { 0x8181, 0x10 }, + { 0x8632, 0x03 }, + }; + + const struct reg_sequence lt9211c_rx_input_sel_seq[] =3D { + { 0xd004, 0x00 }, + { 0xd021, 0x46 }, + }; + + const struct reg_sequence lt9211c_rx_dig_seq[] =3D { + { 0x853f, 0x08 }, + { 0x8540, 0x04 }, + { 0x8541, 0x03 }, + { 0x8542, 0x02 }, + { 0x8543, 0x01 }, + { 0x8545, 0x04 }, + { 0x8546, 0x03 }, + { 0x8547, 0x02 }, + { 0x8548, 0x01 }, + { 0x8544, 0x00 }, + { 0x8549, 0x00 }, + }; + + int ret; + + ret =3D regmap_multi_reg_write(ctx->regmap, lt9211c_rx_phy_seq, + ARRAY_SIZE(lt9211c_rx_phy_seq)); + if (ret) + return ret; + + ret =3D regmap_multi_reg_write(ctx->regmap, lt9211c_rx_phy_reset_seq, + ARRAY_SIZE(lt9211c_rx_phy_reset_seq)); + if (ret) + return ret; + + ret =3D regmap_multi_reg_write(ctx->regmap, lt9211c_rx_clk_sel_seq, + ARRAY_SIZE(lt9211c_rx_clk_sel_seq)); + if (ret) + return ret; + + ret =3D regmap_read(ctx->regmap, 0x8180, &pval); + if (ret) + return ret; + + ret =3D regmap_write(ctx->regmap, 0x8180, (pval & 0xfc | 0x03)); + if (ret) + return ret; + + ret =3D regmap_read(ctx->regmap, 0x8680, &pval); + if (ret) + return ret; + + ret =3D regmap_write(ctx->regmap, 0x863f, (pval & 0xf8)); + if (ret) + return ret; + + ret =3D regmap_write(ctx->regmap, 0x863f, 0x05); + if (ret) + return ret; + + ret =3D regmap_read(ctx->regmap, 0x8530, &pval); + if (ret) + return ret; + + ret =3D regmap_write(ctx->regmap, 0x8530, (pval & 0xf8 | 0x11)); + if (ret) + return ret; + + ret =3D regmap_multi_reg_write(ctx->regmap, lt9211c_rx_input_sel_seq, + ARRAY_SIZE(lt9211c_rx_input_sel_seq)); + if (ret) + return ret; + + ret =3D regmap_multi_reg_write(ctx->regmap, lt9211c_rx_dig_seq, + ARRAY_SIZE(lt9211c_rx_dig_seq)); + if (ret) + return ret; + + /* Give the chip time to lock onto RX stream. */ + msleep(100); + + return 0; +} + +static int lt9211c_autodetect_rx(struct lt9211c *ctx, + const struct drm_display_mode *mode) +{ + u16 width, height; + u8 buf[5]; + u8 format; + u8 bc[3]; + u8 sot[8]; + int ret; + + /* Read the SOT from the chip. */ + ret =3D regmap_bulk_read(ctx->regmap, 0xd088, sot, sizeof(sot)); + if (ret) + return ret; + + dev_dbg(ctx->dev, "Sot Num =3D 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", + sot[0], sot[2], sot[4], sot[6]); + + dev_dbg(ctx->dev, "Sot Data =3D 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", + sot[1], sot[3], sot[5], sot[7]); + + /* HS Settle Set */ + if ((sot[0] > 0x10) && (sot[0] < 0x50)) + regmap_write(ctx->regmap, 0xd002, sot[0] - 5); + else + regmap_write(ctx->regmap, 0xd002, 0x08); + + /* Width/Height/Format Auto-detection */ + ret =3D regmap_bulk_read(ctx->regmap, 0xd082, buf, sizeof(buf)); + if (ret) + return ret; + + width =3D (buf[0] << 8) | buf[1]; + height =3D (buf[3] << 8) | buf[4]; + format =3D buf[2] & 0xf; + + if (format =3D=3D 0x3) { /* YUV422 16bit */ + width /=3D 2; + } else if (format =3D=3D 0xa) { /* RGB888 24bit */ + width /=3D 3; + } else { + dev_err(ctx->dev, "Unsupported DSI format 0x%01x\n", + format); + return -EINVAL; + } + + if (width !=3D mode->hdisplay) { + dev_err(ctx->dev, + "RX: Detected DSI width (%d) does not match mode hdisplay (%d)\n", + width, mode->hdisplay); + return -EINVAL; + } + + if (height !=3D mode->vdisplay) { + dev_err(ctx->dev, + "RX: Detected DSI height (%d) does not match mode vdisplay (%d)\n", + height, mode->vdisplay); + return -EINVAL; + } + + dev_dbg(ctx->dev, "RX: %dx%d format=3D0x%01x\n", + width, height, format); + + return 0; +} + +static int lt9211c_configure_timing(struct lt9211c *ctx, + const struct drm_display_mode *mode) +{ + const struct reg_sequence lt9211c_timing[] =3D { + { 0xd00d, (mode->vtotal >> 8) & 0xff }, + { 0xd00e, mode->vtotal & 0xff }, + { 0xd00f, (mode->vdisplay >> 8) & 0xff }, + { 0xd010, mode->vdisplay & 0xff }, + { 0xd011, (mode->htotal >> 8) & 0xff }, + { 0xd012, mode->htotal & 0xff }, + { 0xd013, (mode->hdisplay >> 8) & 0xff }, + { 0xd014, mode->hdisplay & 0xff }, + { 0xd015, (mode->vsync_end - mode->vsync_start) & 0xff }, + { 0xd04c, ((mode->hsync_end - mode->hsync_start) >> 8) & 0xff }, + { 0xd016, (mode->hsync_end - mode->hsync_start) & 0xff }, + { 0xd017, ((mode->vsync_start - mode->vdisplay) >> 8) & 0xff }, + { 0xd018, (mode->vsync_start - mode->vdisplay) & 0xff }, + { 0xd019, ((mode->hsync_start - mode->hdisplay) >> 8) & 0xff }, + { 0xd01a, (mode->hsync_start - mode->hdisplay) & 0xff }, + }; + + return regmap_multi_reg_write(ctx->regmap, lt9211c_timing, + ARRAY_SIZE(lt9211c_timing)); +} + +static int lt9211c_configure_plls(struct lt9211c *ctx, + const struct drm_display_mode *mode) +{ + const struct reg_sequence lt9211c_dessc_pll_reset[] =3D { + { 0x8103, 0xfe, 2000 }, + { 0x8103, 0xff, 0 }, + }; + + const struct reg_sequence lt9211c_pcr_cali_seq[] =3D { + { 0xd00a, 0x5f }, + { 0xd01e, 0x51 }, + { 0xd023, 0x80 }, + { 0xd024, 0x70 }, + { 0xd025, 0x80 }, + { 0xd02a, 0x10 }, + { 0xd021, 0x4f }, + { 0xd022, 0xf0 }, + { 0xd038, 0x04 }, + { 0xd039, 0x08 }, + { 0xd03a, 0x10 }, + { 0xd03b, 0x20 }, + { 0xd03f, 0x04 }, + { 0xd040, 0x08 }, + { 0xd041, 0x10 }, + { 0xd042, 0x20 }, + { 0xd02b, 0xA0 }, + }; + + const struct reg_sequence lt9211c_pcr_reset_seq[] =3D { + { 0xd009, 0xdb }, + { 0xd009, 0xdf }, + { 0xd008, 0x80 }, + { 0xd008, 0x00 }, + }; + + unsigned int pval; + int ret; + u8 div; + u32 pcr_m; + u32 pcr_k; + u32 pcr_up; + u32 pcr_down; + + /* DeSSC PLL reference clock is 25 MHz XTal. */ + ret =3D regmap_write(ctx->regmap, 0x8226, 0x20); + if (ret) + return ret; + + /* Prediv =3D 0 */ + ret =3D regmap_write(ctx->regmap, 0x8227, 0x40); + if (ret) + return ret; + + if (mode->clock < 22000) { + ret =3D regmap_write(ctx->regmap, 0x822f, 0x07); + ret |=3D regmap_write(ctx->regmap, 0x822c, 0x01); + div =3D 16; + } else if (mode->clock < 44000) { + ret =3D regmap_write(ctx->regmap, 0x822f, 0x07); + div =3D 16; + } else if (mode->clock < 88000) { + ret =3D regmap_write(ctx->regmap, 0x822f, 0x06); + div =3D 8; + } else if (mode->clock < 176000) { + ret =3D regmap_write(ctx->regmap, 0x822f, 0x05); + div =3D 4; + } else { + ret =3D regmap_write(ctx->regmap, 0x822f, 0x04); + div =3D 2; + } + + if (ret) + return ret; + + pcr_m =3D (mode->clock * div) / 25; + pcr_k =3D pcr_m % 1000; + pcr_m /=3D 1000; + + pcr_up =3D pcr_m + 1; + pcr_down =3D pcr_m - 1; + + pcr_k <<=3D 14; + + ret =3D regmap_write(ctx->regmap, 0xd008, 0x00); + if (ret < 0) + return ret; + + /* 0xd026: pcr_m */ + ret =3D regmap_write(ctx->regmap, 0xd026, (0x80 | (u8)pcr_m) & 0x7f); + if (ret < 0) + return ret; + + /* 0xd027 0xd028 0xd029: pcr_k */ + ret =3D regmap_write(ctx->regmap, 0xd027, (pcr_k >> 16) & 0xff); + if (ret < 0) + return ret; + + ret =3D regmap_write(ctx->regmap, 0xd028, (pcr_k >> 8) & 0xff); + if (ret < 0) + return ret; + + ret =3D regmap_write(ctx->regmap, 0xd029, pcr_k & 0xff); + if (ret < 0) + return ret; + + /* 0xd02d: pcr_m overflow limit setting */ + ret =3D regmap_write(ctx->regmap, 0xd02d, pcr_up); + if (ret < 0) + return ret; + + /* 0xd031: pcr_m underflow limit setting */ + ret =3D regmap_write(ctx->regmap, 0xd031, pcr_down); + if (ret < 0) + return ret; + + ret =3D regmap_multi_reg_write(ctx->regmap, lt9211c_dessc_pll_reset, + ARRAY_SIZE(lt9211c_dessc_pll_reset)); + if (ret) + return ret; + + ret =3D regmap_multi_reg_write(ctx->regmap, lt9211c_pcr_cali_seq, + ARRAY_SIZE(lt9211c_pcr_cali_seq)); + if (ret) + return ret; + + if (mode->clock < 44000) { + ret =3D regmap_write(ctx->regmap, 0xd00c, 0x60); + ret |=3D regmap_write(ctx->regmap, 0xd01b, 0x00); + ret |=3D regmap_write(ctx->regmap, 0xd01c, 0x60); + } else { + ret =3D regmap_write(ctx->regmap, 0xd00c, 0x40); + ret |=3D regmap_write(ctx->regmap, 0xd01b, 0x00); + ret |=3D regmap_write(ctx->regmap, 0xd01c, 0x40); + } + if (ret) + return ret; + + ret =3D regmap_multi_reg_write(ctx->regmap, lt9211c_pcr_reset_seq, + ARRAY_SIZE(lt9211c_pcr_reset_seq)); + if (ret) + return ret; + + + /* PCR stability test takes seconds. */ + ret =3D regmap_read_poll_timeout(ctx->regmap, 0xd087, pval, ((pval & 0x18= ) =3D=3D 0x18), + 20000, 3000000); + if (ret) + dev_err(ctx->dev, "PCR unstable, ret=3D%i\n", ret); + + ret =3D regmap_write(ctx->regmap, 0x8180, 0x51); + if (ret) + return ret; + + ret =3D regmap_write(ctx->regmap, 0x863f, 0x00); + if (ret) + return ret; + + ret =3D regmap_write(ctx->regmap, 0x863f, 0x01); + if (ret) + return ret; + + ret =3D regmap_read_poll_timeout(ctx->regmap, 0x8640, pval, ((pval & 0x01= ) =3D=3D 0x01), + 50000, 250000); + if (ret) + dev_err(ctx->dev, "Video check not stable, ret=3D%i\n", ret); + + return ret; +} + +static int lt9211c_configure_tx(struct lt9211c *ctx, + const struct drm_display_mode *mode) +{ + const struct reg_sequence lt9211c_tx_phy_off_seq[] =3D { + { 0x8236, 0x00 }, + { 0x8237, 0x00 }, + { 0x8108, 0x6f }, + { 0x8103, 0xbf }, + }; + + const struct reg_sequence lt9211c_tx_phy_seq[] =3D { + { 0x8236, 0x03 }, + { 0x8237, 0x44 }, + { 0x8238, 0x14 }, + { 0x8239, 0x31 }, + { 0x823a, 0xc8 }, + { 0x823b, 0x00 }, + { 0x823c, 0x0f }, + { 0x8246, 0x40 }, + { 0x8247, 0x40 }, + { 0x8248, 0x40 }, + { 0x8249, 0x40 }, + { 0x824a, 0x40 }, + { 0x824b, 0x40 }, + { 0x824c, 0x40 }, + { 0x824d, 0x40 }, + { 0x824e, 0x40 }, + { 0x824f, 0x40 }, + { 0x8250, 0x40 }, + { 0x8251, 0x40 }, + }; + + const struct reg_sequence lt9211c_tx_mltx_reset[] =3D { + { 0x8103, 0xbf }, + { 0x8103, 0xff }, + }; + + const struct reg_sequence lt9211c_tx_dig_seq[] =3D { + { 0x854a, 0x01 }, + { 0x854b, 0x00 }, + { 0x854c, 0x10 }, + { 0x854d, 0x20 }, + { 0x854e, 0x50 }, + { 0x854f, 0x30 }, + { 0x8550, 0x46 }, + { 0x8551, 0x10 }, + { 0x8552, 0x20 }, + { 0x8553, 0x50 }, + { 0x8554, 0x30 }, + { 0x8555, 0x00 }, + { 0x8556, 0x20 }, + + { 0x8568, 0x00 }, + { 0x856e, 0x10 | (ctx->de ? BIT(6) : 0)}, + { 0x856f, 0x81 | (ctx->jeida ? BIT(6) : 0) | + (ctx->lvds_dual_link ? BIT(4) : 0) | + (ctx->bpp24 ? BIT(2) : 0)}, + }; + + const struct reg_sequence lt9211c_tx_ssc_seq[] =3D { + { 0x8234, 0x00 }, + { 0x856e, 0x10 }, + { 0x8181, 0x15 }, + { 0x871e, 0x00 }, + { 0x8717, 0x02 }, + { 0x8718, 0x04 }, + { 0x8719, 0xd4 }, + { 0x871a, 0x00 }, + { 0x871b, 0x12 }, + { 0x871c, 0x00 }, + { 0x871d, 0x24 }, + { 0x871f, 0x1c }, + { 0x8720, 0x00 }, + { 0x8721, 0x00 }, + { 0x871e, 0x02 }, + }; + + const struct reg_sequence lt9211c_tx_pll_reset_seq[] =3D { + { 0x810c, 0xfe, 2000 }, + { 0x810c, 0xff, 0 }, + }; + + const struct reg_sequence lt9211c_tx_sw_reset_seq[] =3D { + { 0x8108, 0x6f, 2000 }, + { 0x8108, 0x7f, 0 }, + }; + + unsigned int pval; + int ret; + u32 phy_clk; + u8 pixclk_div; + u8 pre_div; + u8 div_set; + u8 sericlk_div; + u8 val; + + dev_info(ctx->dev, "dual_link=3D%d,even_odd_swap=3D%d,bpp24=3D%d,jeida=3D= %d,de=3D%d\n", + ctx->lvds_dual_link, + ctx->lvds_dual_link_even_odd_swap, + ctx->bpp24, + ctx->jeida, + ctx->de); + + ret =3D regmap_multi_reg_write(ctx->regmap, lt9211c_tx_phy_off_seq, + ARRAY_SIZE(lt9211c_tx_phy_off_seq)); + if (ret) + return ret; + + ret =3D regmap_read(ctx->regmap, 0x8530, &pval); + if (ret) + return ret; + + ret =3D regmap_write(ctx->regmap, 0x8530, (pval & 0x3f | 0x40)); + if (ret) + return ret; + + /* [7]0:txpll normal work; txpll ref clk sel pix clk */ + ret =3D regmap_write(ctx->regmap, 0x8230, 0x00); + if (ret) + return ret; + + if (ctx->lvds_dual_link) + phy_clk =3D (u32)(mode->clock * 7 / 2); + else + phy_clk =3D (u32)(mode->clock * 7); + + /* 0x8231: prediv sel */ + if (mode->clock < 20000) { + val =3D 0x28; + pre_div =3D 1; + } else if (mode->clock < 40000) { + val =3D 0x28; + pre_div =3D 1; + } else if (mode->clock < 80000) { + val =3D 0x29; + pre_div =3D 2; + } else if (mode->clock < 160000) { + val =3D 0x2a; + pre_div =3D 4; + } else if (mode->clock < 320000) { + val =3D 0x2b; + pre_div =3D 8; + } else { + val =3D 0x2f; + pre_div =3D 16; + } + ret =3D regmap_write(ctx->regmap, 0x8231, val); + if (ret < 0) + return ret; + + /* 0x8232: serickdiv sel */ + if (phy_clk < 80000) { + val =3D 0x32; + sericlk_div =3D 16; + } else if (phy_clk < 160000) { + val =3D 0x22; + sericlk_div =3D 8; + } else if (phy_clk < 320000) { + val =3D 0x12; + sericlk_div =3D 4; + } else if (phy_clk < 640000) { + val =3D 0x02; + sericlk_div =3D 2; + } else { + val =3D 0x42; + sericlk_div =3D 1; + } + ret =3D regmap_write(ctx->regmap, 0x8232, val); + if (ret < 0) + return ret; + + /* 0x8233: pix_mux sel & pix_div sel + * To avoid floating point operations, The pixclk_div is enlarged by 10 t= imes + */ + if (mode->clock > 150000) { + val =3D 0x04; + pixclk_div =3D 35; + } else { + pixclk_div =3D (u8)((phy_clk * sericlk_div * 10) / (mode->clock * 7)); + if (pixclk_div <=3D 10) + val =3D 0x00; + else if (pixclk_div <=3D 20) + val =3D 0x01; + else if (pixclk_div <=3D 40) + val =3D 0x02; + else + val =3D 0x03; + } + ret =3D regmap_write(ctx->regmap, 0x8233, val); + if (ret < 0) + return ret; + + ret =3D regmap_write(ctx->regmap, 0x8234, 0x01); + if (ret < 0) + return ret; + + /* 0x8235: div set */ + div_set =3D (u8)(phy_clk * sericlk_div / mode->clock / pre_div); + ret =3D regmap_write(ctx->regmap, 0x8235, div_set); + if (ret < 0) + return ret; + + ret =3D regmap_multi_reg_write(ctx->regmap, lt9211c_tx_ssc_seq, + ARRAY_SIZE(lt9211c_tx_ssc_seq)); + if (ret) + return ret; + + ret =3D regmap_multi_reg_write(ctx->regmap, lt9211c_tx_pll_reset_seq, + ARRAY_SIZE(lt9211c_tx_pll_reset_seq)); + if (ret) + return ret; + + ret =3D regmap_read_poll_timeout(ctx->regmap, 0x8739, pval, pval & 0x04, + 10000, 1000000); + if (ret) { + dev_err(ctx->dev, "TX PLL unstable, ret=3D%i\n", ret); + return ret; + } + + ret =3D regmap_multi_reg_write(ctx->regmap, lt9211c_tx_phy_seq, + ARRAY_SIZE(lt9211c_tx_phy_seq)); + if (ret) + return ret; + + ret =3D regmap_multi_reg_write(ctx->regmap, lt9211c_tx_mltx_reset, + ARRAY_SIZE(lt9211c_tx_mltx_reset)); + if (ret) + return ret; + + ret =3D regmap_multi_reg_write(ctx->regmap, lt9211c_tx_dig_seq, + ARRAY_SIZE(lt9211c_tx_dig_seq)); + if (ret) + return ret; + + ret =3D regmap_multi_reg_write(ctx->regmap, lt9211c_tx_sw_reset_seq, + ARRAY_SIZE(lt9211c_tx_sw_reset_seq)); + if (ret) + return ret; + + return 0; +} + +static void lt9211c_delayed_work_func(struct work_struct *work) +{ + struct delayed_work *dw =3D to_delayed_work(work); + struct lt9211c *ctx =3D container_of(dw, struct lt9211c, lt9211c_dw); + int ret; + const struct drm_display_mode *mode =3D &ctx->mode; + + ret =3D lt9211c_configure_rx(ctx); + if (ret) + return; + + ret =3D lt9211c_autodetect_rx(ctx, mode); + if (ret) + return; + + ret =3D lt9211c_configure_timing(ctx, mode); + if (ret) + return; + + ret =3D lt9211c_configure_plls(ctx, mode); + if (ret) + return; + + ret =3D lt9211c_configure_tx(ctx, mode); + if (ret) + return; +} + +static void lt9211c_atomic_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) +{ + struct lt9211c *ctx =3D bridge_to_lt9211c(bridge); + struct drm_atomic_state *state =3D old_bridge_state->base.state; + const struct drm_bridge_state *bridge_state; + const struct drm_crtc_state *crtc_state; + struct drm_connector *connector; + struct drm_crtc *crtc; + u32 bus_flags; + int ret; + + ret =3D regulator_enable(ctx->vccio); + if (ret) { + dev_err(ctx->dev, "Failed to enable vccio: %d\n", ret); + return; + } + + /* Deassert reset */ + gpiod_set_value(ctx->reset_gpio, 1); + usleep_range(20000, 21000); /* Very long post-reset delay. */ + + /* Get the LVDS format from the bridge state. */ + bridge_state =3D drm_atomic_get_new_bridge_state(state, bridge); + bus_flags =3D bridge_state->output_bus_cfg.flags; + ctx->de =3D !!(bus_flags & DRM_BUS_FLAG_DE_HIGH); + + switch (bridge_state->output_bus_cfg.format) { + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: + ctx->bpp24 =3D false; + ctx->jeida =3D true; + break; + case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: + ctx->bpp24 =3D true; + ctx->jeida =3D true; + break; + case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: + ctx->bpp24 =3D true; + ctx->jeida =3D false; + break; + default: + /* + * Some bridges still don't set the correct + * LVDS bus format, use SPWG24 default + * format until those are fixed. + */ + ctx->bpp24 =3D true; + ctx->jeida =3D false; + dev_warn(ctx->dev, + "Unsupported LVDS bus format 0x%04x\n", + bridge_state->output_bus_cfg.format); + break; + } + + /* + * Retrieve the CRTC adjusted mode. This requires a little dance to go + * from the bridge to the encoder, to the connector and to the CRTC. + */ + connector =3D drm_atomic_get_new_connector_for_encoder(state, + bridge->encoder); + crtc =3D drm_atomic_get_new_connector_state(state, connector)->crtc; + crtc_state =3D drm_atomic_get_new_crtc_state(state, crtc); + drm_mode_copy(&ctx->mode, &crtc_state->adjusted_mode); + + dev_dbg(ctx->dev, "width=3D%d,height=3D%d,clock=3D%d\n", + ctx->mode.hdisplay, + ctx->mode.vdisplay, + ctx->mode.clock); + + ret =3D lt9211c_read_chipid(ctx); + if (ret) + return; + + /* Lt9211c must enable after mipi clock enable */ + queue_delayed_work(ctx->wq, &ctx->lt9211c_dw, + msecs_to_jiffies(100)); + + dev_dbg(ctx->dev, "LT9211 enabled.\n"); +} + +static void lt9211c_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) +{ + struct lt9211c *ctx =3D bridge_to_lt9211c(bridge); + int ret; + + /* + * Put the chip in reset, pull nRST line low, + * and assure lengthy 10ms reset low timing. + */ + gpiod_set_value(ctx->reset_gpio, 0); + usleep_range(10000, 11000); /* Very long reset duration. */ + + ret =3D regulator_disable(ctx->vccio); + if (ret) + dev_err(ctx->dev, "Failed to disable vccio: %d\n", ret); + + regcache_mark_dirty(ctx->regmap); +} + +static enum drm_mode_status +lt9211c_mode_valid(struct drm_bridge *bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) +{ + /* LVDS output clock range 25..176 MHz */ + if (mode->clock < 25000) + return MODE_CLOCK_LOW; + if (mode->clock > 176000) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +#define MAX_INPUT_SEL_FORMATS 1 + +static u32 * +lt9211c_atomic_get_input_bus_fmts(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + u32 output_fmt, + unsigned int *num_input_fmts) +{ + u32 *input_fmts; + + *num_input_fmts =3D 0; + + input_fmts =3D kcalloc(MAX_INPUT_SEL_FORMATS, sizeof(*input_fmts), + GFP_KERNEL); + if (!input_fmts) + return NULL; + + /* This is the DSI-end bus format */ + input_fmts[0] =3D MEDIA_BUS_FMT_RGB888_1X24; + *num_input_fmts =3D 1; + + return input_fmts; +} + +static const struct drm_bridge_funcs lt9211c_funcs =3D { + .attach =3D lt9211c_attach, + .mode_valid =3D lt9211c_mode_valid, + .atomic_enable =3D lt9211c_atomic_enable, + .atomic_disable =3D lt9211c_atomic_disable, + .atomic_duplicate_state =3D drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state =3D drm_atomic_helper_bridge_destroy_state, + .atomic_get_input_bus_fmts =3D lt9211c_atomic_get_input_bus_fmts, + .atomic_reset =3D drm_atomic_helper_bridge_reset, +}; + +static int lt9211c_parse_dt(struct lt9211c *ctx) +{ + struct device_node *port2, *port3; + struct drm_bridge *panel_bridge; + struct device *dev =3D ctx->dev; + struct drm_panel *panel; + int dual_link; + int ret; + + ctx->vccio =3D devm_regulator_get(dev, "vccio"); + if (IS_ERR(ctx->vccio)) + return dev_err_probe(dev, PTR_ERR(ctx->vccio), + "Failed to get supply 'vccio'\n"); + + ctx->lvds_dual_link =3D false; + ctx->lvds_dual_link_even_odd_swap =3D false; + + port2 =3D of_graph_get_port_by_id(dev->of_node, 2); + port3 =3D of_graph_get_port_by_id(dev->of_node, 3); + dual_link =3D drm_of_lvds_get_dual_link_pixel_order(port2, port3); + of_node_put(port2); + of_node_put(port3); + + if (dual_link =3D=3D DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS) { + ctx->lvds_dual_link =3D true; + /* Odd pixels to LVDS Channel A, even pixels to B */ + ctx->lvds_dual_link_even_odd_swap =3D false; + } else if (dual_link =3D=3D DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS) { + ctx->lvds_dual_link =3D true; + /* Even pixels to LVDS Channel A, odd pixels to B */ + ctx->lvds_dual_link_even_odd_swap =3D true; + } + + ret =3D drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &panel, &panel_br= idge); + if (ret < 0) + return ret; + if (panel) { + panel_bridge =3D devm_drm_panel_bridge_add(dev, panel); + if (IS_ERR(panel_bridge)) + return PTR_ERR(panel_bridge); + } + + ctx->panel_bridge =3D panel_bridge; + + return 0; +} + +static int lt9211c_host_attach(struct lt9211c *ctx) +{ + const struct mipi_dsi_device_info info =3D { + .type =3D "lt9211c", + .channel =3D 0, + .node =3D NULL, + }; + struct device *dev =3D ctx->dev; + struct device_node *host_node; + struct device_node *endpoint; + struct mipi_dsi_device *dsi; + struct mipi_dsi_host *host; + int dsi_lanes; + int ret; + + endpoint =3D of_graph_get_endpoint_by_regs(dev->of_node, 0, -1); + dsi_lanes =3D drm_of_get_data_lanes_count(endpoint, 1, 4); + host_node =3D of_graph_get_remote_port_parent(endpoint); + host =3D of_find_mipi_dsi_host_by_node(host_node); + of_node_put(host_node); + of_node_put(endpoint); + + if (!host) + return -EPROBE_DEFER; + + if (dsi_lanes < 0) + return dsi_lanes; + + dsi =3D devm_mipi_dsi_device_register_full(dev, host, &info); + if (IS_ERR(dsi)) + return dev_err_probe(dev, PTR_ERR(dsi), + "failed to create dsi device\n"); + + ctx->dsi =3D dsi; + + dsi->lanes =3D dsi_lanes; + dsi->format =3D MIPI_DSI_FMT_RGB888; + dsi->mode_flags =3D MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM; + + ret =3D devm_mipi_dsi_attach(dev, dsi); + if (ret < 0) { + dev_err(dev, "failed to attach dsi to host: %d\n", ret); + return ret; + } + + return 0; +} + +static int lt9211c_probe(struct i2c_client *client) +{ + struct device *dev =3D &client->dev; + struct lt9211c *ctx; + int ret; + + ctx =3D devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->dev =3D dev; + + /* + * Put the chip in reset, pull nRST line low, + * and assure lengthy 10ms reset low timing. + */ + ctx->reset_gpio =3D devm_gpiod_get_optional(ctx->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(ctx->reset_gpio)) + return PTR_ERR(ctx->reset_gpio); + + usleep_range(10000, 11000); /* Very long reset duration. */ + + ret =3D lt9211c_parse_dt(ctx); + if (ret) + return ret; + + ctx->regmap =3D devm_regmap_init_i2c(client, <9211c_regmap_config); + if (IS_ERR(ctx->regmap)) + return PTR_ERR(ctx->regmap); + + dev_set_drvdata(dev, ctx); + i2c_set_clientdata(client, ctx); + + ctx->bridge.funcs =3D <9211c_funcs; + ctx->bridge.of_node =3D dev->of_node; + drm_bridge_add(&ctx->bridge); + + ret =3D lt9211c_host_attach(ctx); + if (ret) + drm_bridge_remove(&ctx->bridge); + + ctx->wq =3D create_workqueue("lt9211c_work"); + INIT_DELAYED_WORK(&ctx->lt9211c_dw, lt9211c_delayed_work_func); + + return ret; +} + +static void lt9211c_remove(struct i2c_client *client) +{ + struct lt9211c *ctx =3D i2c_get_clientdata(client); + + cancel_delayed_work(&ctx->lt9211c_dw); + destroy_workqueue(ctx->wq); + + drm_bridge_remove(&ctx->bridge); +} + +static struct i2c_device_id lt9211c_id[] =3D { + { "lontium,lt9211c" }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, lt9211c_id); + +static const struct of_device_id lt9211c_match_table[] =3D { + { .compatible =3D "lontium,lt9211c" }, + {}, +}; +MODULE_DEVICE_TABLE(of, lt9211c_match_table); + +static struct i2c_driver lt9211c_driver =3D { + .probe =3D lt9211c_probe, + .remove =3D lt9211c_remove, + .id_table =3D lt9211c_id, + .driver =3D { + .name =3D "lt9211c", + .of_match_table =3D lt9211c_match_table, + }, +}; +module_i2c_driver(lt9211c_driver); + +MODULE_AUTHOR("Yi Zhang "); +MODULE_DESCRIPTION("Lontium LT9211C DSI/LVDS/DPI bridge driver"); +MODULE_LICENSE("GPL"); --=20 2.50.1