Skip to content

Commit 442f34e

Browse files
pbguyen-baylibrevinodkoul
authored andcommitted
phy: mtk-mipi-csi: add driver for CSI phy
This is a new driver that supports the MIPI CSI CD-PHY version 0.5 The number of PHYs depend on the SoC. Each PHY can support D-PHY only or CD-PHY configuration. The driver supports only D-PHY mode, so CD-PHY compatible PHY are configured in D-PHY mode. [Julien Stephan: simplify driver model: one instance per phy vs one instance for all phys] Signed-off-by: Louis Kuo <louis.kuo@mediatek.com> Signed-off-by: Phi-bang Nguyen <pnguyen@baylibre.com> [Julien Stephan: refactor code] Co-developed-by: Julien Stephan <jstephan@baylibre.com> Signed-off-by: Julien Stephan <jstephan@baylibre.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Link: https://lore.kernel.org/r/20240111101738.468916-1-jstephan@baylibre.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent a41baa4 commit 442f34e

File tree

5 files changed

+371
-0
lines changed

5 files changed

+371
-0
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13746,6 +13746,7 @@ M: Julien Stephan <jstephan@baylibre.com>
1374613746
M: Andy Hsieh <andy.hsieh@mediatek.com>
1374713747
S: Supported
1374813748
F: Documentation/devicetree/bindings/phy/mediatek,mt8365-csi-rx.yaml
13749+
F: drivers/phy/mediatek/phy-mtk-mipi-csi-0-5*
1374913750

1375013751
MEDIATEK MMC/SD/SDIO DRIVER
1375113752
M: Chaotian Jing <chaotian.jing@mediatek.com>

drivers/phy/mediatek/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,18 @@ config PHY_MTK_HDMI
5858
help
5959
Support HDMI PHY for Mediatek SoCs.
6060

61+
config PHY_MTK_MIPI_CSI_0_5
62+
tristate "MediaTek MIPI CSI CD-PHY v0.5 Driver"
63+
depends on ARCH_MEDIATEK || COMPILE_TEST
64+
depends on OF
65+
select GENERIC_PHY
66+
help
67+
Enable this to support the MIPI CSI CD-PHY receiver version 0.5.
68+
The driver supports multiple CSI cdphy ports simultaneously.
69+
70+
To compile this driver as a module, choose M here: the
71+
module will be called phy-mtk-mipi-csi-0-5.
72+
6173
config PHY_MTK_MIPI_DSI
6274
tristate "MediaTek MIPI-DSI Driver"
6375
depends on ARCH_MEDIATEK || COMPILE_TEST

drivers/phy/mediatek/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ phy-mtk-hdmi-drv-y += phy-mtk-hdmi-mt8173.o
1515
phy-mtk-hdmi-drv-y += phy-mtk-hdmi-mt8195.o
1616
obj-$(CONFIG_PHY_MTK_HDMI) += phy-mtk-hdmi-drv.o
1717

18+
obj-$(CONFIG_PHY_MTK_MIPI_CSI_0_5) += phy-mtk-mipi-csi-0-5.o
19+
1820
phy-mtk-mipi-dsi-drv-y := phy-mtk-mipi-dsi.o
1921
phy-mtk-mipi-dsi-drv-y += phy-mtk-mipi-dsi-mt8173.o
2022
phy-mtk-mipi-dsi-drv-y += phy-mtk-mipi-dsi-mt8183.o
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (c) 2023, MediaTek Inc.
4+
* Copyright (c) 2023, BayLibre Inc.
5+
*/
6+
7+
#ifndef __PHY_MTK_MIPI_CSI_V_0_5_RX_REG_H__
8+
#define __PHY_MTK_MIPI_CSI_V_0_5_RX_REG_H__
9+
10+
/*
11+
* CSI1 and CSI2 are identical, and similar to CSI0. All CSIX macros are
12+
* applicable to the three PHYs. Where differences exist, they are denoted by
13+
* macro names using CSI0 and CSI1, the latter being applicable to CSI1 and
14+
* CSI2 alike.
15+
*/
16+
17+
#define MIPI_RX_ANA00_CSIXA 0x0000
18+
#define RG_CSI0A_CPHY_EN BIT(0)
19+
#define RG_CSIXA_EQ_PROTECT_EN BIT(1)
20+
#define RG_CSIXA_BG_LPF_EN BIT(2)
21+
#define RG_CSIXA_BG_CORE_EN BIT(3)
22+
#define RG_CSIXA_DPHY_L0_CKMODE_EN BIT(5)
23+
#define RG_CSIXA_DPHY_L0_CKSEL BIT(6)
24+
#define RG_CSIXA_DPHY_L1_CKMODE_EN BIT(8)
25+
#define RG_CSIXA_DPHY_L1_CKSEL BIT(9)
26+
#define RG_CSIXA_DPHY_L2_CKMODE_EN BIT(11)
27+
#define RG_CSIXA_DPHY_L2_CKSEL BIT(12)
28+
29+
#define MIPI_RX_ANA18_CSIXA 0x0018
30+
#define RG_CSI0A_L0_T0AB_EQ_IS GENMASK(5, 4)
31+
#define RG_CSI0A_L0_T0AB_EQ_BW GENMASK(7, 6)
32+
#define RG_CSI0A_L1_T1AB_EQ_IS GENMASK(21, 20)
33+
#define RG_CSI0A_L1_T1AB_EQ_BW GENMASK(23, 22)
34+
#define RG_CSI0A_L2_T1BC_EQ_IS GENMASK(21, 20)
35+
#define RG_CSI0A_L2_T1BC_EQ_BW GENMASK(23, 22)
36+
#define RG_CSI1A_L0_EQ_IS GENMASK(5, 4)
37+
#define RG_CSI1A_L0_EQ_BW GENMASK(7, 6)
38+
#define RG_CSI1A_L1_EQ_IS GENMASK(21, 20)
39+
#define RG_CSI1A_L1_EQ_BW GENMASK(23, 22)
40+
#define RG_CSI1A_L2_EQ_IS GENMASK(5, 4)
41+
#define RG_CSI1A_L2_EQ_BW GENMASK(7, 6)
42+
43+
#define MIPI_RX_ANA1C_CSIXA 0x001c
44+
#define MIPI_RX_ANA20_CSI0A 0x0020
45+
46+
#define MIPI_RX_ANA24_CSIXA 0x0024
47+
#define RG_CSIXA_RESERVE GENMASK(31, 24)
48+
49+
#define MIPI_RX_ANA40_CSIXA 0x0040
50+
#define RG_CSIXA_CPHY_FMCK_SEL GENMASK(1, 0)
51+
#define RG_CSIXA_ASYNC_OPTION GENMASK(7, 4)
52+
#define RG_CSIXA_CPHY_SPARE GENMASK(31, 16)
53+
54+
#define MIPI_RX_WRAPPER80_CSIXA 0x0080
55+
#define CSR_CSI_RST_MODE GENMASK(17, 16)
56+
57+
#define MIPI_RX_ANAA8_CSIXA 0x00a8
58+
#define RG_CSIXA_CDPHY_L0_T0_BYTECK_INVERT BIT(0)
59+
#define RG_CSIXA_DPHY_L1_BYTECK_INVERT BIT(1)
60+
#define RG_CSIXA_CDPHY_L2_T1_BYTECK_INVERT BIT(2)
61+
62+
#endif
Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* MediaTek MIPI CSI v0.5 driver
4+
*
5+
* Copyright (c) 2023, MediaTek Inc.
6+
* Copyright (c) 2023, BayLibre Inc.
7+
*/
8+
9+
#include <dt-bindings/phy/phy.h>
10+
#include <linux/bitfield.h>
11+
#include <linux/delay.h>
12+
#include <linux/io.h>
13+
#include <linux/module.h>
14+
#include <linux/mutex.h>
15+
#include <linux/phy/phy.h>
16+
#include <linux/platform_device.h>
17+
#include <linux/slab.h>
18+
19+
#include "phy-mtk-io.h"
20+
#include "phy-mtk-mipi-csi-0-5-rx-reg.h"
21+
22+
#define CSIXB_OFFSET 0x1000
23+
24+
struct mtk_mipi_cdphy_port {
25+
struct device *dev;
26+
void __iomem *base;
27+
struct phy *phy;
28+
u32 type;
29+
u32 mode;
30+
u32 num_lanes;
31+
};
32+
33+
enum PHY_TYPE {
34+
DPHY = 0,
35+
CPHY,
36+
CDPHY,
37+
};
38+
39+
static void mtk_phy_csi_cdphy_ana_eq_tune(void __iomem *base)
40+
{
41+
mtk_phy_update_field(base + MIPI_RX_ANA18_CSIXA, RG_CSI0A_L0_T0AB_EQ_IS, 1);
42+
mtk_phy_update_field(base + MIPI_RX_ANA18_CSIXA, RG_CSI0A_L0_T0AB_EQ_BW, 1);
43+
mtk_phy_update_field(base + MIPI_RX_ANA1C_CSIXA, RG_CSI0A_L1_T1AB_EQ_IS, 1);
44+
mtk_phy_update_field(base + MIPI_RX_ANA1C_CSIXA, RG_CSI0A_L1_T1AB_EQ_BW, 1);
45+
mtk_phy_update_field(base + MIPI_RX_ANA20_CSI0A, RG_CSI0A_L2_T1BC_EQ_IS, 1);
46+
mtk_phy_update_field(base + MIPI_RX_ANA20_CSI0A, RG_CSI0A_L2_T1BC_EQ_BW, 1);
47+
48+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA18_CSIXA, RG_CSI0A_L0_T0AB_EQ_IS, 1);
49+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA18_CSIXA, RG_CSI0A_L0_T0AB_EQ_BW, 1);
50+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA1C_CSIXA, RG_CSI0A_L1_T1AB_EQ_IS, 1);
51+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA1C_CSIXA, RG_CSI0A_L1_T1AB_EQ_BW, 1);
52+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA20_CSI0A, RG_CSI0A_L2_T1BC_EQ_IS, 1);
53+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA20_CSI0A, RG_CSI0A_L2_T1BC_EQ_BW, 1);
54+
}
55+
56+
static void mtk_phy_csi_dphy_ana_eq_tune(void __iomem *base)
57+
{
58+
mtk_phy_update_field(base + MIPI_RX_ANA18_CSIXA, RG_CSI1A_L0_EQ_IS, 1);
59+
mtk_phy_update_field(base + MIPI_RX_ANA18_CSIXA, RG_CSI1A_L0_EQ_BW, 1);
60+
mtk_phy_update_field(base + MIPI_RX_ANA18_CSIXA, RG_CSI1A_L1_EQ_IS, 1);
61+
mtk_phy_update_field(base + MIPI_RX_ANA18_CSIXA, RG_CSI1A_L1_EQ_BW, 1);
62+
mtk_phy_update_field(base + MIPI_RX_ANA1C_CSIXA, RG_CSI1A_L2_EQ_IS, 1);
63+
mtk_phy_update_field(base + MIPI_RX_ANA1C_CSIXA, RG_CSI1A_L2_EQ_BW, 1);
64+
65+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA18_CSIXA, RG_CSI1A_L0_EQ_IS, 1);
66+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA18_CSIXA, RG_CSI1A_L0_EQ_BW, 1);
67+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA18_CSIXA, RG_CSI1A_L1_EQ_IS, 1);
68+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA18_CSIXA, RG_CSI1A_L1_EQ_BW, 1);
69+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA1C_CSIXA, RG_CSI1A_L2_EQ_IS, 1);
70+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA1C_CSIXA, RG_CSI1A_L2_EQ_BW, 1);
71+
}
72+
73+
static int mtk_mipi_phy_power_on(struct phy *phy)
74+
{
75+
struct mtk_mipi_cdphy_port *port = phy_get_drvdata(phy);
76+
void __iomem *base = port->base;
77+
78+
/*
79+
* The driver currently supports DPHY and CD-PHY phys,
80+
* but the only mode supported is DPHY,
81+
* so CD-PHY capable phys must be configured in DPHY mode
82+
*/
83+
if (port->type == CDPHY) {
84+
mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSI0A_CPHY_EN, 0);
85+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA,
86+
RG_CSI0A_CPHY_EN, 0);
87+
}
88+
89+
/*
90+
* Lane configuration:
91+
*
92+
* Only 4 data + 1 clock is supported for now with the following mapping:
93+
*
94+
* CSIXA_LNR0 --> D2
95+
* CSIXA_LNR1 --> D0
96+
* CSIXA_LNR2 --> C
97+
* CSIXB_LNR0 --> D1
98+
* CSIXB_LNR1 --> D3
99+
*/
100+
mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L0_CKMODE_EN, 0);
101+
mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L0_CKSEL, 1);
102+
mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L1_CKMODE_EN, 0);
103+
mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L1_CKSEL, 1);
104+
mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L2_CKMODE_EN, 1);
105+
mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L2_CKSEL, 1);
106+
107+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA,
108+
RG_CSIXA_DPHY_L0_CKMODE_EN, 0);
109+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L0_CKSEL, 1);
110+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA,
111+
RG_CSIXA_DPHY_L1_CKMODE_EN, 0);
112+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L1_CKSEL, 1);
113+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA,
114+
RG_CSIXA_DPHY_L2_CKMODE_EN, 0);
115+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA, RG_CSIXA_DPHY_L2_CKSEL, 1);
116+
117+
/* Byte clock invert */
118+
mtk_phy_update_field(base + MIPI_RX_ANAA8_CSIXA, RG_CSIXA_CDPHY_L0_T0_BYTECK_INVERT, 1);
119+
mtk_phy_update_field(base + MIPI_RX_ANAA8_CSIXA, RG_CSIXA_DPHY_L1_BYTECK_INVERT, 1);
120+
mtk_phy_update_field(base + MIPI_RX_ANAA8_CSIXA, RG_CSIXA_CDPHY_L2_T1_BYTECK_INVERT, 1);
121+
122+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANAA8_CSIXA,
123+
RG_CSIXA_CDPHY_L0_T0_BYTECK_INVERT, 1);
124+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANAA8_CSIXA,
125+
RG_CSIXA_DPHY_L1_BYTECK_INVERT, 1);
126+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANAA8_CSIXA,
127+
RG_CSIXA_CDPHY_L2_T1_BYTECK_INVERT, 1);
128+
129+
/* Start ANA EQ tuning */
130+
if (port->type == CDPHY)
131+
mtk_phy_csi_cdphy_ana_eq_tune(base);
132+
else
133+
mtk_phy_csi_dphy_ana_eq_tune(base);
134+
135+
/* End ANA EQ tuning */
136+
mtk_phy_set_bits(base + MIPI_RX_ANA40_CSIXA, 0x90);
137+
138+
mtk_phy_update_field(base + MIPI_RX_ANA24_CSIXA, RG_CSIXA_RESERVE, 0x40);
139+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA24_CSIXA, RG_CSIXA_RESERVE, 0x40);
140+
mtk_phy_update_field(base + MIPI_RX_WRAPPER80_CSIXA, CSR_CSI_RST_MODE, 0);
141+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_WRAPPER80_CSIXA, CSR_CSI_RST_MODE, 0);
142+
/* ANA power on */
143+
mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_BG_CORE_EN, 1);
144+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA, RG_CSIXA_BG_CORE_EN, 1);
145+
usleep_range(20, 40);
146+
mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_BG_LPF_EN, 1);
147+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA, RG_CSIXA_BG_LPF_EN, 1);
148+
149+
return 0;
150+
}
151+
152+
static int mtk_mipi_phy_power_off(struct phy *phy)
153+
{
154+
struct mtk_mipi_cdphy_port *port = phy_get_drvdata(phy);
155+
void __iomem *base = port->base;
156+
157+
/* Disable MIPI BG. */
158+
mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_BG_CORE_EN, 0);
159+
mtk_phy_update_field(base + MIPI_RX_ANA00_CSIXA, RG_CSIXA_BG_LPF_EN, 0);
160+
161+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA, RG_CSIXA_BG_CORE_EN, 0);
162+
mtk_phy_update_field(base + CSIXB_OFFSET + MIPI_RX_ANA00_CSIXA, RG_CSIXA_BG_LPF_EN, 0);
163+
164+
return 0;
165+
}
166+
167+
static struct phy *mtk_mipi_cdphy_xlate(struct device *dev,
168+
struct of_phandle_args *args)
169+
{
170+
struct mtk_mipi_cdphy_port *priv = dev_get_drvdata(dev);
171+
172+
/*
173+
* If PHY is CD-PHY then we need to get the operating mode
174+
* For now only D-PHY mode is supported
175+
*/
176+
if (priv->type == CDPHY) {
177+
if (args->args_count != 1) {
178+
dev_err(dev, "invalid number of arguments\n");
179+
return ERR_PTR(-EINVAL);
180+
}
181+
switch (args->args[0]) {
182+
case PHY_TYPE_DPHY:
183+
priv->mode = DPHY;
184+
if (priv->num_lanes != 4) {
185+
dev_err(dev, "Only 4D1C mode is supported for now!\n");
186+
return ERR_PTR(-EINVAL);
187+
}
188+
break;
189+
default:
190+
dev_err(dev, "Unsupported PHY type: %i\n", args->args[0]);
191+
return ERR_PTR(-EINVAL);
192+
}
193+
} else {
194+
if (args->args_count) {
195+
dev_err(dev, "invalid number of arguments\n");
196+
return ERR_PTR(-EINVAL);
197+
}
198+
priv->mode = DPHY;
199+
}
200+
201+
return priv->phy;
202+
}
203+
204+
static const struct phy_ops mtk_cdphy_ops = {
205+
.power_on = mtk_mipi_phy_power_on,
206+
.power_off = mtk_mipi_phy_power_off,
207+
.owner = THIS_MODULE,
208+
};
209+
210+
static int mtk_mipi_cdphy_probe(struct platform_device *pdev)
211+
{
212+
struct device *dev = &pdev->dev;
213+
struct phy_provider *phy_provider;
214+
struct mtk_mipi_cdphy_port *port;
215+
struct phy *phy;
216+
int ret;
217+
u32 phy_type;
218+
219+
port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
220+
if (!port)
221+
return -ENOMEM;
222+
223+
dev_set_drvdata(dev, port);
224+
225+
port->dev = dev;
226+
227+
port->base = devm_platform_ioremap_resource(pdev, 0);
228+
if (IS_ERR(port->base))
229+
return PTR_ERR(port->base);
230+
231+
ret = of_property_read_u32(dev->of_node, "num-lanes", &port->num_lanes);
232+
if (ret) {
233+
dev_err(dev, "Failed to read num-lanes property: %i\n", ret);
234+
return ret;
235+
}
236+
237+
/*
238+
* phy-type is optional, if not present, PHY is considered to be CD-PHY
239+
*/
240+
if (device_property_present(dev, "phy-type")) {
241+
ret = of_property_read_u32(dev->of_node, "phy-type", &phy_type);
242+
if (ret) {
243+
dev_err(dev, "Failed to read phy-type property: %i\n", ret);
244+
return ret;
245+
}
246+
switch (phy_type) {
247+
case PHY_TYPE_DPHY:
248+
port->type = DPHY;
249+
break;
250+
default:
251+
dev_err(dev, "Unsupported PHY type: %i\n", phy_type);
252+
return -EINVAL;
253+
}
254+
} else {
255+
port->type = CDPHY;
256+
}
257+
258+
phy = devm_phy_create(dev, NULL, &mtk_cdphy_ops);
259+
if (IS_ERR(phy)) {
260+
dev_err(dev, "Failed to create PHY: %ld\n", PTR_ERR(phy));
261+
return PTR_ERR(phy);
262+
}
263+
264+
port->phy = phy;
265+
phy_set_drvdata(phy, port);
266+
267+
phy_provider = devm_of_phy_provider_register(dev, mtk_mipi_cdphy_xlate);
268+
if (IS_ERR(phy_provider)) {
269+
dev_err(dev, "Failed to register PHY provider: %ld\n",
270+
PTR_ERR(phy_provider));
271+
return PTR_ERR(phy_provider);
272+
}
273+
274+
return 0;
275+
}
276+
277+
static const struct of_device_id mtk_mipi_cdphy_of_match[] = {
278+
{ .compatible = "mediatek,mt8365-csi-rx" },
279+
{ /* sentinel */},
280+
};
281+
MODULE_DEVICE_TABLE(of, mtk_mipi_cdphy_of_match);
282+
283+
static struct platform_driver mipi_cdphy_pdrv = {
284+
.probe = mtk_mipi_cdphy_probe,
285+
.driver = {
286+
.name = "mtk-mipi-csi-0-5",
287+
.of_match_table = mtk_mipi_cdphy_of_match,
288+
},
289+
};
290+
module_platform_driver(mipi_cdphy_pdrv);
291+
292+
MODULE_DESCRIPTION("MediaTek MIPI CSI CD-PHY v0.5 Driver");
293+
MODULE_AUTHOR("Louis Kuo <louis.kuo@mediatek.com>");
294+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)