1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (c) 2015 MediaTek Inc.
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <linux/clk.h>
7*4882a593Smuzhiyun #include <linux/component.h>
8*4882a593Smuzhiyun #include <linux/iopoll.h>
9*4882a593Smuzhiyun #include <linux/irq.h>
10*4882a593Smuzhiyun #include <linux/of.h>
11*4882a593Smuzhiyun #include <linux/of_platform.h>
12*4882a593Smuzhiyun #include <linux/phy/phy.h>
13*4882a593Smuzhiyun #include <linux/platform_device.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include <video/mipi_display.h>
16*4882a593Smuzhiyun #include <video/videomode.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #include <drm/drm_atomic_helper.h>
19*4882a593Smuzhiyun #include <drm/drm_bridge.h>
20*4882a593Smuzhiyun #include <drm/drm_bridge_connector.h>
21*4882a593Smuzhiyun #include <drm/drm_mipi_dsi.h>
22*4882a593Smuzhiyun #include <drm/drm_of.h>
23*4882a593Smuzhiyun #include <drm/drm_panel.h>
24*4882a593Smuzhiyun #include <drm/drm_print.h>
25*4882a593Smuzhiyun #include <drm/drm_probe_helper.h>
26*4882a593Smuzhiyun #include <drm/drm_simple_kms_helper.h>
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #include "mtk_drm_ddp_comp.h"
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #define DSI_START 0x00
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #define DSI_INTEN 0x08
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #define DSI_INTSTA 0x0c
35*4882a593Smuzhiyun #define LPRX_RD_RDY_INT_FLAG BIT(0)
36*4882a593Smuzhiyun #define CMD_DONE_INT_FLAG BIT(1)
37*4882a593Smuzhiyun #define TE_RDY_INT_FLAG BIT(2)
38*4882a593Smuzhiyun #define VM_DONE_INT_FLAG BIT(3)
39*4882a593Smuzhiyun #define EXT_TE_RDY_INT_FLAG BIT(4)
40*4882a593Smuzhiyun #define DSI_BUSY BIT(31)
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun #define DSI_CON_CTRL 0x10
43*4882a593Smuzhiyun #define DSI_RESET BIT(0)
44*4882a593Smuzhiyun #define DSI_EN BIT(1)
45*4882a593Smuzhiyun #define DPHY_RESET BIT(2)
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun #define DSI_MODE_CTRL 0x14
48*4882a593Smuzhiyun #define MODE (3)
49*4882a593Smuzhiyun #define CMD_MODE 0
50*4882a593Smuzhiyun #define SYNC_PULSE_MODE 1
51*4882a593Smuzhiyun #define SYNC_EVENT_MODE 2
52*4882a593Smuzhiyun #define BURST_MODE 3
53*4882a593Smuzhiyun #define FRM_MODE BIT(16)
54*4882a593Smuzhiyun #define MIX_MODE BIT(17)
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #define DSI_TXRX_CTRL 0x18
57*4882a593Smuzhiyun #define VC_NUM BIT(1)
58*4882a593Smuzhiyun #define LANE_NUM (0xf << 2)
59*4882a593Smuzhiyun #define DIS_EOT BIT(6)
60*4882a593Smuzhiyun #define NULL_EN BIT(7)
61*4882a593Smuzhiyun #define TE_FREERUN BIT(8)
62*4882a593Smuzhiyun #define EXT_TE_EN BIT(9)
63*4882a593Smuzhiyun #define EXT_TE_EDGE BIT(10)
64*4882a593Smuzhiyun #define MAX_RTN_SIZE (0xf << 12)
65*4882a593Smuzhiyun #define HSTX_CKLP_EN BIT(16)
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun #define DSI_PSCTRL 0x1c
68*4882a593Smuzhiyun #define DSI_PS_WC 0x3fff
69*4882a593Smuzhiyun #define DSI_PS_SEL (3 << 16)
70*4882a593Smuzhiyun #define PACKED_PS_16BIT_RGB565 (0 << 16)
71*4882a593Smuzhiyun #define LOOSELY_PS_18BIT_RGB666 (1 << 16)
72*4882a593Smuzhiyun #define PACKED_PS_18BIT_RGB666 (2 << 16)
73*4882a593Smuzhiyun #define PACKED_PS_24BIT_RGB888 (3 << 16)
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun #define DSI_VSA_NL 0x20
76*4882a593Smuzhiyun #define DSI_VBP_NL 0x24
77*4882a593Smuzhiyun #define DSI_VFP_NL 0x28
78*4882a593Smuzhiyun #define DSI_VACT_NL 0x2C
79*4882a593Smuzhiyun #define DSI_SIZE_CON 0x38
80*4882a593Smuzhiyun #define DSI_HSA_WC 0x50
81*4882a593Smuzhiyun #define DSI_HBP_WC 0x54
82*4882a593Smuzhiyun #define DSI_HFP_WC 0x58
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun #define DSI_CMDQ_SIZE 0x60
85*4882a593Smuzhiyun #define CMDQ_SIZE 0x3f
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun #define DSI_HSTX_CKL_WC 0x64
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun #define DSI_RX_DATA0 0x74
90*4882a593Smuzhiyun #define DSI_RX_DATA1 0x78
91*4882a593Smuzhiyun #define DSI_RX_DATA2 0x7c
92*4882a593Smuzhiyun #define DSI_RX_DATA3 0x80
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun #define DSI_RACK 0x84
95*4882a593Smuzhiyun #define RACK BIT(0)
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun #define DSI_PHY_LCCON 0x104
98*4882a593Smuzhiyun #define LC_HS_TX_EN BIT(0)
99*4882a593Smuzhiyun #define LC_ULPM_EN BIT(1)
100*4882a593Smuzhiyun #define LC_WAKEUP_EN BIT(2)
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun #define DSI_PHY_LD0CON 0x108
103*4882a593Smuzhiyun #define LD0_HS_TX_EN BIT(0)
104*4882a593Smuzhiyun #define LD0_ULPM_EN BIT(1)
105*4882a593Smuzhiyun #define LD0_WAKEUP_EN BIT(2)
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun #define DSI_PHY_TIMECON0 0x110
108*4882a593Smuzhiyun #define LPX (0xff << 0)
109*4882a593Smuzhiyun #define HS_PREP (0xff << 8)
110*4882a593Smuzhiyun #define HS_ZERO (0xff << 16)
111*4882a593Smuzhiyun #define HS_TRAIL (0xff << 24)
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun #define DSI_PHY_TIMECON1 0x114
114*4882a593Smuzhiyun #define TA_GO (0xff << 0)
115*4882a593Smuzhiyun #define TA_SURE (0xff << 8)
116*4882a593Smuzhiyun #define TA_GET (0xff << 16)
117*4882a593Smuzhiyun #define DA_HS_EXIT (0xff << 24)
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun #define DSI_PHY_TIMECON2 0x118
120*4882a593Smuzhiyun #define CONT_DET (0xff << 0)
121*4882a593Smuzhiyun #define CLK_ZERO (0xff << 16)
122*4882a593Smuzhiyun #define CLK_TRAIL (0xff << 24)
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun #define DSI_PHY_TIMECON3 0x11c
125*4882a593Smuzhiyun #define CLK_HS_PREP (0xff << 0)
126*4882a593Smuzhiyun #define CLK_HS_POST (0xff << 8)
127*4882a593Smuzhiyun #define CLK_HS_EXIT (0xff << 16)
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun #define DSI_VM_CMD_CON 0x130
130*4882a593Smuzhiyun #define VM_CMD_EN BIT(0)
131*4882a593Smuzhiyun #define TS_VFP_EN BIT(5)
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun #define DSI_SHADOW_DEBUG 0x190U
134*4882a593Smuzhiyun #define FORCE_COMMIT BIT(0)
135*4882a593Smuzhiyun #define BYPASS_SHADOW BIT(1)
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun #define CONFIG (0xff << 0)
138*4882a593Smuzhiyun #define SHORT_PACKET 0
139*4882a593Smuzhiyun #define LONG_PACKET 2
140*4882a593Smuzhiyun #define BTA BIT(2)
141*4882a593Smuzhiyun #define DATA_ID (0xff << 8)
142*4882a593Smuzhiyun #define DATA_0 (0xff << 16)
143*4882a593Smuzhiyun #define DATA_1 (0xff << 24)
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun #define NS_TO_CYCLE(n, c) ((n) / (c) + (((n) % (c)) ? 1 : 0))
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun #define MTK_DSI_HOST_IS_READ(type) \
148*4882a593Smuzhiyun ((type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) || \
149*4882a593Smuzhiyun (type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) || \
150*4882a593Smuzhiyun (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \
151*4882a593Smuzhiyun (type == MIPI_DSI_DCS_READ))
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun struct mtk_phy_timing {
154*4882a593Smuzhiyun u32 lpx;
155*4882a593Smuzhiyun u32 da_hs_prepare;
156*4882a593Smuzhiyun u32 da_hs_zero;
157*4882a593Smuzhiyun u32 da_hs_trail;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun u32 ta_go;
160*4882a593Smuzhiyun u32 ta_sure;
161*4882a593Smuzhiyun u32 ta_get;
162*4882a593Smuzhiyun u32 da_hs_exit;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun u32 clk_hs_zero;
165*4882a593Smuzhiyun u32 clk_hs_trail;
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun u32 clk_hs_prepare;
168*4882a593Smuzhiyun u32 clk_hs_post;
169*4882a593Smuzhiyun u32 clk_hs_exit;
170*4882a593Smuzhiyun };
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun struct phy;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun struct mtk_dsi_driver_data {
175*4882a593Smuzhiyun const u32 reg_cmdq_off;
176*4882a593Smuzhiyun bool has_shadow_ctl;
177*4882a593Smuzhiyun bool has_size_ctl;
178*4882a593Smuzhiyun };
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun struct mtk_dsi {
181*4882a593Smuzhiyun struct mtk_ddp_comp ddp_comp;
182*4882a593Smuzhiyun struct device *dev;
183*4882a593Smuzhiyun struct mipi_dsi_host host;
184*4882a593Smuzhiyun struct drm_encoder encoder;
185*4882a593Smuzhiyun struct drm_bridge bridge;
186*4882a593Smuzhiyun struct drm_bridge *next_bridge;
187*4882a593Smuzhiyun struct drm_connector *connector;
188*4882a593Smuzhiyun struct phy *phy;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun void __iomem *regs;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun struct clk *engine_clk;
193*4882a593Smuzhiyun struct clk *digital_clk;
194*4882a593Smuzhiyun struct clk *hs_clk;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun u32 data_rate;
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun unsigned long mode_flags;
199*4882a593Smuzhiyun enum mipi_dsi_pixel_format format;
200*4882a593Smuzhiyun unsigned int lanes;
201*4882a593Smuzhiyun struct videomode vm;
202*4882a593Smuzhiyun struct mtk_phy_timing phy_timing;
203*4882a593Smuzhiyun int refcount;
204*4882a593Smuzhiyun bool enabled;
205*4882a593Smuzhiyun bool lanes_ready;
206*4882a593Smuzhiyun u32 irq_data;
207*4882a593Smuzhiyun wait_queue_head_t irq_wait_queue;
208*4882a593Smuzhiyun const struct mtk_dsi_driver_data *driver_data;
209*4882a593Smuzhiyun };
210*4882a593Smuzhiyun
bridge_to_dsi(struct drm_bridge * b)211*4882a593Smuzhiyun static inline struct mtk_dsi *bridge_to_dsi(struct drm_bridge *b)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun return container_of(b, struct mtk_dsi, bridge);
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun
host_to_dsi(struct mipi_dsi_host * h)216*4882a593Smuzhiyun static inline struct mtk_dsi *host_to_dsi(struct mipi_dsi_host *h)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun return container_of(h, struct mtk_dsi, host);
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
mtk_dsi_mask(struct mtk_dsi * dsi,u32 offset,u32 mask,u32 data)221*4882a593Smuzhiyun static void mtk_dsi_mask(struct mtk_dsi *dsi, u32 offset, u32 mask, u32 data)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun u32 temp = readl(dsi->regs + offset);
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun writel((temp & ~mask) | (data & mask), dsi->regs + offset);
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun
mtk_dsi_phy_timconfig(struct mtk_dsi * dsi)228*4882a593Smuzhiyun static void mtk_dsi_phy_timconfig(struct mtk_dsi *dsi)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun u32 timcon0, timcon1, timcon2, timcon3;
231*4882a593Smuzhiyun u32 data_rate_mhz = DIV_ROUND_UP(dsi->data_rate, 1000000);
232*4882a593Smuzhiyun struct mtk_phy_timing *timing = &dsi->phy_timing;
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun timing->lpx = (60 * data_rate_mhz / (8 * 1000)) + 1;
235*4882a593Smuzhiyun timing->da_hs_prepare = (80 * data_rate_mhz + 4 * 1000) / 8000;
236*4882a593Smuzhiyun timing->da_hs_zero = (170 * data_rate_mhz + 10 * 1000) / 8000 + 1 -
237*4882a593Smuzhiyun timing->da_hs_prepare;
238*4882a593Smuzhiyun timing->da_hs_trail = timing->da_hs_prepare + 1;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun timing->ta_go = 4 * timing->lpx - 2;
241*4882a593Smuzhiyun timing->ta_sure = timing->lpx + 2;
242*4882a593Smuzhiyun timing->ta_get = 4 * timing->lpx;
243*4882a593Smuzhiyun timing->da_hs_exit = 2 * timing->lpx + 1;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun timing->clk_hs_prepare = 70 * data_rate_mhz / (8 * 1000);
246*4882a593Smuzhiyun timing->clk_hs_post = timing->clk_hs_prepare + 8;
247*4882a593Smuzhiyun timing->clk_hs_trail = timing->clk_hs_prepare;
248*4882a593Smuzhiyun timing->clk_hs_zero = timing->clk_hs_trail * 4;
249*4882a593Smuzhiyun timing->clk_hs_exit = 2 * timing->clk_hs_trail;
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun timcon0 = timing->lpx | timing->da_hs_prepare << 8 |
252*4882a593Smuzhiyun timing->da_hs_zero << 16 | timing->da_hs_trail << 24;
253*4882a593Smuzhiyun timcon1 = timing->ta_go | timing->ta_sure << 8 |
254*4882a593Smuzhiyun timing->ta_get << 16 | timing->da_hs_exit << 24;
255*4882a593Smuzhiyun timcon2 = 1 << 8 | timing->clk_hs_zero << 16 |
256*4882a593Smuzhiyun timing->clk_hs_trail << 24;
257*4882a593Smuzhiyun timcon3 = timing->clk_hs_prepare | timing->clk_hs_post << 8 |
258*4882a593Smuzhiyun timing->clk_hs_exit << 16;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun writel(timcon0, dsi->regs + DSI_PHY_TIMECON0);
261*4882a593Smuzhiyun writel(timcon1, dsi->regs + DSI_PHY_TIMECON1);
262*4882a593Smuzhiyun writel(timcon2, dsi->regs + DSI_PHY_TIMECON2);
263*4882a593Smuzhiyun writel(timcon3, dsi->regs + DSI_PHY_TIMECON3);
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun
mtk_dsi_enable(struct mtk_dsi * dsi)266*4882a593Smuzhiyun static void mtk_dsi_enable(struct mtk_dsi *dsi)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, DSI_EN);
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
mtk_dsi_disable(struct mtk_dsi * dsi)271*4882a593Smuzhiyun static void mtk_dsi_disable(struct mtk_dsi *dsi)
272*4882a593Smuzhiyun {
273*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, 0);
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun
mtk_dsi_reset_engine(struct mtk_dsi * dsi)276*4882a593Smuzhiyun static void mtk_dsi_reset_engine(struct mtk_dsi *dsi)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, DSI_RESET);
279*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, 0);
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun
mtk_dsi_reset_dphy(struct mtk_dsi * dsi)282*4882a593Smuzhiyun static void mtk_dsi_reset_dphy(struct mtk_dsi *dsi)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_CON_CTRL, DPHY_RESET, DPHY_RESET);
285*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_CON_CTRL, DPHY_RESET, 0);
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
mtk_dsi_clk_ulp_mode_enter(struct mtk_dsi * dsi)288*4882a593Smuzhiyun static void mtk_dsi_clk_ulp_mode_enter(struct mtk_dsi *dsi)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0);
291*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0);
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun
mtk_dsi_clk_ulp_mode_leave(struct mtk_dsi * dsi)294*4882a593Smuzhiyun static void mtk_dsi_clk_ulp_mode_leave(struct mtk_dsi *dsi)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0);
297*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, LC_WAKEUP_EN);
298*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, 0);
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
mtk_dsi_lane0_ulp_mode_enter(struct mtk_dsi * dsi)301*4882a593Smuzhiyun static void mtk_dsi_lane0_ulp_mode_enter(struct mtk_dsi *dsi)
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_HS_TX_EN, 0);
304*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0);
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun
mtk_dsi_lane0_ulp_mode_leave(struct mtk_dsi * dsi)307*4882a593Smuzhiyun static void mtk_dsi_lane0_ulp_mode_leave(struct mtk_dsi *dsi)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0);
310*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, LD0_WAKEUP_EN);
311*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, 0);
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun
mtk_dsi_clk_hs_state(struct mtk_dsi * dsi)314*4882a593Smuzhiyun static bool mtk_dsi_clk_hs_state(struct mtk_dsi *dsi)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun return readl(dsi->regs + DSI_PHY_LCCON) & LC_HS_TX_EN;
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun
mtk_dsi_clk_hs_mode(struct mtk_dsi * dsi,bool enter)319*4882a593Smuzhiyun static void mtk_dsi_clk_hs_mode(struct mtk_dsi *dsi, bool enter)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun if (enter && !mtk_dsi_clk_hs_state(dsi))
322*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, LC_HS_TX_EN);
323*4882a593Smuzhiyun else if (!enter && mtk_dsi_clk_hs_state(dsi))
324*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0);
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun
mtk_dsi_set_mode(struct mtk_dsi * dsi)327*4882a593Smuzhiyun static void mtk_dsi_set_mode(struct mtk_dsi *dsi)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun u32 vid_mode = CMD_MODE;
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
332*4882a593Smuzhiyun if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
333*4882a593Smuzhiyun vid_mode = BURST_MODE;
334*4882a593Smuzhiyun else if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
335*4882a593Smuzhiyun vid_mode = SYNC_PULSE_MODE;
336*4882a593Smuzhiyun else
337*4882a593Smuzhiyun vid_mode = SYNC_EVENT_MODE;
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun writel(vid_mode, dsi->regs + DSI_MODE_CTRL);
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
mtk_dsi_set_vm_cmd(struct mtk_dsi * dsi)343*4882a593Smuzhiyun static void mtk_dsi_set_vm_cmd(struct mtk_dsi *dsi)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_VM_CMD_CON, VM_CMD_EN, VM_CMD_EN);
346*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_VM_CMD_CON, TS_VFP_EN, TS_VFP_EN);
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun
mtk_dsi_ps_control_vact(struct mtk_dsi * dsi)349*4882a593Smuzhiyun static void mtk_dsi_ps_control_vact(struct mtk_dsi *dsi)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun struct videomode *vm = &dsi->vm;
352*4882a593Smuzhiyun u32 dsi_buf_bpp, ps_wc;
353*4882a593Smuzhiyun u32 ps_bpp_mode;
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun if (dsi->format == MIPI_DSI_FMT_RGB565)
356*4882a593Smuzhiyun dsi_buf_bpp = 2;
357*4882a593Smuzhiyun else
358*4882a593Smuzhiyun dsi_buf_bpp = 3;
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun ps_wc = vm->hactive * dsi_buf_bpp;
361*4882a593Smuzhiyun ps_bpp_mode = ps_wc;
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun switch (dsi->format) {
364*4882a593Smuzhiyun case MIPI_DSI_FMT_RGB888:
365*4882a593Smuzhiyun ps_bpp_mode |= PACKED_PS_24BIT_RGB888;
366*4882a593Smuzhiyun break;
367*4882a593Smuzhiyun case MIPI_DSI_FMT_RGB666:
368*4882a593Smuzhiyun ps_bpp_mode |= PACKED_PS_18BIT_RGB666;
369*4882a593Smuzhiyun break;
370*4882a593Smuzhiyun case MIPI_DSI_FMT_RGB666_PACKED:
371*4882a593Smuzhiyun ps_bpp_mode |= LOOSELY_PS_18BIT_RGB666;
372*4882a593Smuzhiyun break;
373*4882a593Smuzhiyun case MIPI_DSI_FMT_RGB565:
374*4882a593Smuzhiyun ps_bpp_mode |= PACKED_PS_16BIT_RGB565;
375*4882a593Smuzhiyun break;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun writel(vm->vactive, dsi->regs + DSI_VACT_NL);
379*4882a593Smuzhiyun writel(ps_bpp_mode, dsi->regs + DSI_PSCTRL);
380*4882a593Smuzhiyun writel(ps_wc, dsi->regs + DSI_HSTX_CKL_WC);
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun
mtk_dsi_rxtx_control(struct mtk_dsi * dsi)383*4882a593Smuzhiyun static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun u32 tmp_reg;
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun switch (dsi->lanes) {
388*4882a593Smuzhiyun case 1:
389*4882a593Smuzhiyun tmp_reg = 1 << 2;
390*4882a593Smuzhiyun break;
391*4882a593Smuzhiyun case 2:
392*4882a593Smuzhiyun tmp_reg = 3 << 2;
393*4882a593Smuzhiyun break;
394*4882a593Smuzhiyun case 3:
395*4882a593Smuzhiyun tmp_reg = 7 << 2;
396*4882a593Smuzhiyun break;
397*4882a593Smuzhiyun case 4:
398*4882a593Smuzhiyun tmp_reg = 0xf << 2;
399*4882a593Smuzhiyun break;
400*4882a593Smuzhiyun default:
401*4882a593Smuzhiyun tmp_reg = 0xf << 2;
402*4882a593Smuzhiyun break;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun tmp_reg |= (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) << 6;
406*4882a593Smuzhiyun tmp_reg |= (dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET) >> 3;
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL);
409*4882a593Smuzhiyun }
410*4882a593Smuzhiyun
mtk_dsi_ps_control(struct mtk_dsi * dsi)411*4882a593Smuzhiyun static void mtk_dsi_ps_control(struct mtk_dsi *dsi)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun u32 dsi_tmp_buf_bpp;
414*4882a593Smuzhiyun u32 tmp_reg;
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun switch (dsi->format) {
417*4882a593Smuzhiyun case MIPI_DSI_FMT_RGB888:
418*4882a593Smuzhiyun tmp_reg = PACKED_PS_24BIT_RGB888;
419*4882a593Smuzhiyun dsi_tmp_buf_bpp = 3;
420*4882a593Smuzhiyun break;
421*4882a593Smuzhiyun case MIPI_DSI_FMT_RGB666:
422*4882a593Smuzhiyun tmp_reg = LOOSELY_PS_18BIT_RGB666;
423*4882a593Smuzhiyun dsi_tmp_buf_bpp = 3;
424*4882a593Smuzhiyun break;
425*4882a593Smuzhiyun case MIPI_DSI_FMT_RGB666_PACKED:
426*4882a593Smuzhiyun tmp_reg = PACKED_PS_18BIT_RGB666;
427*4882a593Smuzhiyun dsi_tmp_buf_bpp = 3;
428*4882a593Smuzhiyun break;
429*4882a593Smuzhiyun case MIPI_DSI_FMT_RGB565:
430*4882a593Smuzhiyun tmp_reg = PACKED_PS_16BIT_RGB565;
431*4882a593Smuzhiyun dsi_tmp_buf_bpp = 2;
432*4882a593Smuzhiyun break;
433*4882a593Smuzhiyun default:
434*4882a593Smuzhiyun tmp_reg = PACKED_PS_24BIT_RGB888;
435*4882a593Smuzhiyun dsi_tmp_buf_bpp = 3;
436*4882a593Smuzhiyun break;
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun tmp_reg += dsi->vm.hactive * dsi_tmp_buf_bpp & DSI_PS_WC;
440*4882a593Smuzhiyun writel(tmp_reg, dsi->regs + DSI_PSCTRL);
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun
mtk_dsi_config_vdo_timing(struct mtk_dsi * dsi)443*4882a593Smuzhiyun static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun u32 horizontal_sync_active_byte;
446*4882a593Smuzhiyun u32 horizontal_backporch_byte;
447*4882a593Smuzhiyun u32 horizontal_frontporch_byte;
448*4882a593Smuzhiyun u32 horizontal_front_back_byte;
449*4882a593Smuzhiyun u32 data_phy_cycles_byte;
450*4882a593Smuzhiyun u32 dsi_tmp_buf_bpp, data_phy_cycles;
451*4882a593Smuzhiyun u32 delta;
452*4882a593Smuzhiyun struct mtk_phy_timing *timing = &dsi->phy_timing;
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun struct videomode *vm = &dsi->vm;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun if (dsi->format == MIPI_DSI_FMT_RGB565)
457*4882a593Smuzhiyun dsi_tmp_buf_bpp = 2;
458*4882a593Smuzhiyun else
459*4882a593Smuzhiyun dsi_tmp_buf_bpp = 3;
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun writel(vm->vsync_len, dsi->regs + DSI_VSA_NL);
462*4882a593Smuzhiyun writel(vm->vback_porch, dsi->regs + DSI_VBP_NL);
463*4882a593Smuzhiyun writel(vm->vfront_porch, dsi->regs + DSI_VFP_NL);
464*4882a593Smuzhiyun writel(vm->vactive, dsi->regs + DSI_VACT_NL);
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun if (dsi->driver_data->has_size_ctl)
467*4882a593Smuzhiyun writel(vm->vactive << 16 | vm->hactive,
468*4882a593Smuzhiyun dsi->regs + DSI_SIZE_CON);
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun horizontal_sync_active_byte = (vm->hsync_len * dsi_tmp_buf_bpp - 10);
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
473*4882a593Smuzhiyun horizontal_backporch_byte = vm->hback_porch * dsi_tmp_buf_bpp - 10;
474*4882a593Smuzhiyun else
475*4882a593Smuzhiyun horizontal_backporch_byte = (vm->hback_porch + vm->hsync_len) *
476*4882a593Smuzhiyun dsi_tmp_buf_bpp - 10;
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun data_phy_cycles = timing->lpx + timing->da_hs_prepare +
479*4882a593Smuzhiyun timing->da_hs_zero + timing->da_hs_exit + 3;
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun delta = dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST ? 18 : 12;
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun horizontal_frontporch_byte = vm->hfront_porch * dsi_tmp_buf_bpp;
484*4882a593Smuzhiyun horizontal_front_back_byte = horizontal_frontporch_byte + horizontal_backporch_byte;
485*4882a593Smuzhiyun data_phy_cycles_byte = data_phy_cycles * dsi->lanes + delta;
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun if (horizontal_front_back_byte > data_phy_cycles_byte) {
488*4882a593Smuzhiyun horizontal_frontporch_byte -= data_phy_cycles_byte *
489*4882a593Smuzhiyun horizontal_frontporch_byte /
490*4882a593Smuzhiyun horizontal_front_back_byte;
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun horizontal_backporch_byte -= data_phy_cycles_byte *
493*4882a593Smuzhiyun horizontal_backporch_byte /
494*4882a593Smuzhiyun horizontal_front_back_byte;
495*4882a593Smuzhiyun } else {
496*4882a593Smuzhiyun DRM_WARN("HFP + HBP less than d-phy, FPS will under 60Hz\n");
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun writel(horizontal_sync_active_byte, dsi->regs + DSI_HSA_WC);
500*4882a593Smuzhiyun writel(horizontal_backporch_byte, dsi->regs + DSI_HBP_WC);
501*4882a593Smuzhiyun writel(horizontal_frontporch_byte, dsi->regs + DSI_HFP_WC);
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun mtk_dsi_ps_control(dsi);
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun
mtk_dsi_start(struct mtk_dsi * dsi)506*4882a593Smuzhiyun static void mtk_dsi_start(struct mtk_dsi *dsi)
507*4882a593Smuzhiyun {
508*4882a593Smuzhiyun writel(0, dsi->regs + DSI_START);
509*4882a593Smuzhiyun writel(1, dsi->regs + DSI_START);
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun
mtk_dsi_stop(struct mtk_dsi * dsi)512*4882a593Smuzhiyun static void mtk_dsi_stop(struct mtk_dsi *dsi)
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun writel(0, dsi->regs + DSI_START);
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun
mtk_dsi_set_cmd_mode(struct mtk_dsi * dsi)517*4882a593Smuzhiyun static void mtk_dsi_set_cmd_mode(struct mtk_dsi *dsi)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun writel(CMD_MODE, dsi->regs + DSI_MODE_CTRL);
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun
mtk_dsi_set_interrupt_enable(struct mtk_dsi * dsi)522*4882a593Smuzhiyun static void mtk_dsi_set_interrupt_enable(struct mtk_dsi *dsi)
523*4882a593Smuzhiyun {
524*4882a593Smuzhiyun u32 inten = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG;
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun writel(inten, dsi->regs + DSI_INTEN);
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun
mtk_dsi_irq_data_set(struct mtk_dsi * dsi,u32 irq_bit)529*4882a593Smuzhiyun static void mtk_dsi_irq_data_set(struct mtk_dsi *dsi, u32 irq_bit)
530*4882a593Smuzhiyun {
531*4882a593Smuzhiyun dsi->irq_data |= irq_bit;
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun
mtk_dsi_irq_data_clear(struct mtk_dsi * dsi,u32 irq_bit)534*4882a593Smuzhiyun static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit)
535*4882a593Smuzhiyun {
536*4882a593Smuzhiyun dsi->irq_data &= ~irq_bit;
537*4882a593Smuzhiyun }
538*4882a593Smuzhiyun
mtk_dsi_wait_for_irq_done(struct mtk_dsi * dsi,u32 irq_flag,unsigned int timeout)539*4882a593Smuzhiyun static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
540*4882a593Smuzhiyun unsigned int timeout)
541*4882a593Smuzhiyun {
542*4882a593Smuzhiyun s32 ret = 0;
543*4882a593Smuzhiyun unsigned long jiffies = msecs_to_jiffies(timeout);
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun ret = wait_event_interruptible_timeout(dsi->irq_wait_queue,
546*4882a593Smuzhiyun dsi->irq_data & irq_flag,
547*4882a593Smuzhiyun jiffies);
548*4882a593Smuzhiyun if (ret == 0) {
549*4882a593Smuzhiyun DRM_WARN("Wait DSI IRQ(0x%08x) Timeout\n", irq_flag);
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun mtk_dsi_enable(dsi);
552*4882a593Smuzhiyun mtk_dsi_reset_engine(dsi);
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun return ret;
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun
mtk_dsi_irq(int irq,void * dev_id)558*4882a593Smuzhiyun static irqreturn_t mtk_dsi_irq(int irq, void *dev_id)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun struct mtk_dsi *dsi = dev_id;
561*4882a593Smuzhiyun u32 status, tmp;
562*4882a593Smuzhiyun u32 flag = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG;
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun status = readl(dsi->regs + DSI_INTSTA) & flag;
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun if (status) {
567*4882a593Smuzhiyun do {
568*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_RACK, RACK, RACK);
569*4882a593Smuzhiyun tmp = readl(dsi->regs + DSI_INTSTA);
570*4882a593Smuzhiyun } while (tmp & DSI_BUSY);
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_INTSTA, status, 0);
573*4882a593Smuzhiyun mtk_dsi_irq_data_set(dsi, status);
574*4882a593Smuzhiyun wake_up_interruptible(&dsi->irq_wait_queue);
575*4882a593Smuzhiyun }
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun return IRQ_HANDLED;
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun
mtk_dsi_switch_to_cmd_mode(struct mtk_dsi * dsi,u8 irq_flag,u32 t)580*4882a593Smuzhiyun static s32 mtk_dsi_switch_to_cmd_mode(struct mtk_dsi *dsi, u8 irq_flag, u32 t)
581*4882a593Smuzhiyun {
582*4882a593Smuzhiyun mtk_dsi_irq_data_clear(dsi, irq_flag);
583*4882a593Smuzhiyun mtk_dsi_set_cmd_mode(dsi);
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun if (!mtk_dsi_wait_for_irq_done(dsi, irq_flag, t)) {
586*4882a593Smuzhiyun DRM_ERROR("failed to switch cmd mode\n");
587*4882a593Smuzhiyun return -ETIME;
588*4882a593Smuzhiyun } else {
589*4882a593Smuzhiyun return 0;
590*4882a593Smuzhiyun }
591*4882a593Smuzhiyun }
592*4882a593Smuzhiyun
mtk_dsi_poweron(struct mtk_dsi * dsi)593*4882a593Smuzhiyun static int mtk_dsi_poweron(struct mtk_dsi *dsi)
594*4882a593Smuzhiyun {
595*4882a593Smuzhiyun struct device *dev = dsi->host.dev;
596*4882a593Smuzhiyun int ret;
597*4882a593Smuzhiyun u32 bit_per_pixel;
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun if (++dsi->refcount != 1)
600*4882a593Smuzhiyun return 0;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun switch (dsi->format) {
603*4882a593Smuzhiyun case MIPI_DSI_FMT_RGB565:
604*4882a593Smuzhiyun bit_per_pixel = 16;
605*4882a593Smuzhiyun break;
606*4882a593Smuzhiyun case MIPI_DSI_FMT_RGB666_PACKED:
607*4882a593Smuzhiyun bit_per_pixel = 18;
608*4882a593Smuzhiyun break;
609*4882a593Smuzhiyun case MIPI_DSI_FMT_RGB666:
610*4882a593Smuzhiyun case MIPI_DSI_FMT_RGB888:
611*4882a593Smuzhiyun default:
612*4882a593Smuzhiyun bit_per_pixel = 24;
613*4882a593Smuzhiyun break;
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun dsi->data_rate = DIV_ROUND_UP_ULL(dsi->vm.pixelclock * bit_per_pixel,
617*4882a593Smuzhiyun dsi->lanes);
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun ret = clk_set_rate(dsi->hs_clk, dsi->data_rate);
620*4882a593Smuzhiyun if (ret < 0) {
621*4882a593Smuzhiyun dev_err(dev, "Failed to set data rate: %d\n", ret);
622*4882a593Smuzhiyun goto err_refcount;
623*4882a593Smuzhiyun }
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun phy_power_on(dsi->phy);
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun ret = clk_prepare_enable(dsi->engine_clk);
628*4882a593Smuzhiyun if (ret < 0) {
629*4882a593Smuzhiyun dev_err(dev, "Failed to enable engine clock: %d\n", ret);
630*4882a593Smuzhiyun goto err_phy_power_off;
631*4882a593Smuzhiyun }
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun ret = clk_prepare_enable(dsi->digital_clk);
634*4882a593Smuzhiyun if (ret < 0) {
635*4882a593Smuzhiyun dev_err(dev, "Failed to enable digital clock: %d\n", ret);
636*4882a593Smuzhiyun goto err_disable_engine_clk;
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun mtk_dsi_enable(dsi);
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun if (dsi->driver_data->has_shadow_ctl)
642*4882a593Smuzhiyun writel(FORCE_COMMIT | BYPASS_SHADOW,
643*4882a593Smuzhiyun dsi->regs + DSI_SHADOW_DEBUG);
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun mtk_dsi_reset_engine(dsi);
646*4882a593Smuzhiyun mtk_dsi_phy_timconfig(dsi);
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun mtk_dsi_ps_control_vact(dsi);
649*4882a593Smuzhiyun mtk_dsi_set_vm_cmd(dsi);
650*4882a593Smuzhiyun mtk_dsi_config_vdo_timing(dsi);
651*4882a593Smuzhiyun mtk_dsi_set_interrupt_enable(dsi);
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun return 0;
654*4882a593Smuzhiyun err_disable_engine_clk:
655*4882a593Smuzhiyun clk_disable_unprepare(dsi->engine_clk);
656*4882a593Smuzhiyun err_phy_power_off:
657*4882a593Smuzhiyun phy_power_off(dsi->phy);
658*4882a593Smuzhiyun err_refcount:
659*4882a593Smuzhiyun dsi->refcount--;
660*4882a593Smuzhiyun return ret;
661*4882a593Smuzhiyun }
662*4882a593Smuzhiyun
mtk_dsi_poweroff(struct mtk_dsi * dsi)663*4882a593Smuzhiyun static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
664*4882a593Smuzhiyun {
665*4882a593Smuzhiyun if (WARN_ON(dsi->refcount == 0))
666*4882a593Smuzhiyun return;
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun if (--dsi->refcount != 0)
669*4882a593Smuzhiyun return;
670*4882a593Smuzhiyun
671*4882a593Smuzhiyun /*
672*4882a593Smuzhiyun * mtk_dsi_stop() and mtk_dsi_start() is asymmetric, since
673*4882a593Smuzhiyun * mtk_dsi_stop() should be called after mtk_drm_crtc_atomic_disable(),
674*4882a593Smuzhiyun * which needs irq for vblank, and mtk_dsi_stop() will disable irq.
675*4882a593Smuzhiyun * mtk_dsi_start() needs to be called in mtk_output_dsi_enable(),
676*4882a593Smuzhiyun * after dsi is fully set.
677*4882a593Smuzhiyun */
678*4882a593Smuzhiyun mtk_dsi_stop(dsi);
679*4882a593Smuzhiyun
680*4882a593Smuzhiyun mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, 500);
681*4882a593Smuzhiyun mtk_dsi_reset_engine(dsi);
682*4882a593Smuzhiyun mtk_dsi_lane0_ulp_mode_enter(dsi);
683*4882a593Smuzhiyun mtk_dsi_clk_ulp_mode_enter(dsi);
684*4882a593Smuzhiyun /* set the lane number as 0 to pull down mipi */
685*4882a593Smuzhiyun writel(0, dsi->regs + DSI_TXRX_CTRL);
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun mtk_dsi_disable(dsi);
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun clk_disable_unprepare(dsi->engine_clk);
690*4882a593Smuzhiyun clk_disable_unprepare(dsi->digital_clk);
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun phy_power_off(dsi->phy);
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun dsi->lanes_ready = false;
695*4882a593Smuzhiyun }
696*4882a593Smuzhiyun
mtk_dsi_lane_ready(struct mtk_dsi * dsi)697*4882a593Smuzhiyun static void mtk_dsi_lane_ready(struct mtk_dsi *dsi)
698*4882a593Smuzhiyun {
699*4882a593Smuzhiyun if (!dsi->lanes_ready) {
700*4882a593Smuzhiyun dsi->lanes_ready = true;
701*4882a593Smuzhiyun mtk_dsi_rxtx_control(dsi);
702*4882a593Smuzhiyun usleep_range(30, 100);
703*4882a593Smuzhiyun mtk_dsi_reset_dphy(dsi);
704*4882a593Smuzhiyun mtk_dsi_clk_ulp_mode_leave(dsi);
705*4882a593Smuzhiyun mtk_dsi_lane0_ulp_mode_leave(dsi);
706*4882a593Smuzhiyun mtk_dsi_clk_hs_mode(dsi, 0);
707*4882a593Smuzhiyun msleep(20);
708*4882a593Smuzhiyun /* The reaction time after pulling up the mipi signal for dsi_rx */
709*4882a593Smuzhiyun }
710*4882a593Smuzhiyun }
711*4882a593Smuzhiyun
mtk_output_dsi_enable(struct mtk_dsi * dsi)712*4882a593Smuzhiyun static void mtk_output_dsi_enable(struct mtk_dsi *dsi)
713*4882a593Smuzhiyun {
714*4882a593Smuzhiyun if (dsi->enabled)
715*4882a593Smuzhiyun return;
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun mtk_dsi_lane_ready(dsi);
718*4882a593Smuzhiyun mtk_dsi_set_mode(dsi);
719*4882a593Smuzhiyun mtk_dsi_clk_hs_mode(dsi, 1);
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun mtk_dsi_start(dsi);
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun dsi->enabled = true;
724*4882a593Smuzhiyun }
725*4882a593Smuzhiyun
mtk_output_dsi_disable(struct mtk_dsi * dsi)726*4882a593Smuzhiyun static void mtk_output_dsi_disable(struct mtk_dsi *dsi)
727*4882a593Smuzhiyun {
728*4882a593Smuzhiyun if (!dsi->enabled)
729*4882a593Smuzhiyun return;
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun dsi->enabled = false;
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun
mtk_dsi_bridge_attach(struct drm_bridge * bridge,enum drm_bridge_attach_flags flags)734*4882a593Smuzhiyun static int mtk_dsi_bridge_attach(struct drm_bridge *bridge,
735*4882a593Smuzhiyun enum drm_bridge_attach_flags flags)
736*4882a593Smuzhiyun {
737*4882a593Smuzhiyun struct mtk_dsi *dsi = bridge_to_dsi(bridge);
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun /* Attach the panel or bridge to the dsi bridge */
740*4882a593Smuzhiyun return drm_bridge_attach(bridge->encoder, dsi->next_bridge,
741*4882a593Smuzhiyun &dsi->bridge, flags);
742*4882a593Smuzhiyun }
743*4882a593Smuzhiyun
mtk_dsi_bridge_mode_set(struct drm_bridge * bridge,const struct drm_display_mode * mode,const struct drm_display_mode * adjusted)744*4882a593Smuzhiyun static void mtk_dsi_bridge_mode_set(struct drm_bridge *bridge,
745*4882a593Smuzhiyun const struct drm_display_mode *mode,
746*4882a593Smuzhiyun const struct drm_display_mode *adjusted)
747*4882a593Smuzhiyun {
748*4882a593Smuzhiyun struct mtk_dsi *dsi = bridge_to_dsi(bridge);
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun drm_display_mode_to_videomode(adjusted, &dsi->vm);
751*4882a593Smuzhiyun }
752*4882a593Smuzhiyun
mtk_dsi_bridge_atomic_disable(struct drm_bridge * bridge,struct drm_bridge_state * old_bridge_state)753*4882a593Smuzhiyun static void mtk_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
754*4882a593Smuzhiyun struct drm_bridge_state *old_bridge_state)
755*4882a593Smuzhiyun {
756*4882a593Smuzhiyun struct mtk_dsi *dsi = bridge_to_dsi(bridge);
757*4882a593Smuzhiyun
758*4882a593Smuzhiyun mtk_output_dsi_disable(dsi);
759*4882a593Smuzhiyun }
760*4882a593Smuzhiyun
mtk_dsi_bridge_atomic_enable(struct drm_bridge * bridge,struct drm_bridge_state * old_bridge_state)761*4882a593Smuzhiyun static void mtk_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
762*4882a593Smuzhiyun struct drm_bridge_state *old_bridge_state)
763*4882a593Smuzhiyun {
764*4882a593Smuzhiyun struct mtk_dsi *dsi = bridge_to_dsi(bridge);
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun if (dsi->refcount == 0)
767*4882a593Smuzhiyun return;
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun mtk_output_dsi_enable(dsi);
770*4882a593Smuzhiyun }
771*4882a593Smuzhiyun
mtk_dsi_bridge_atomic_pre_enable(struct drm_bridge * bridge,struct drm_bridge_state * old_bridge_state)772*4882a593Smuzhiyun static void mtk_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
773*4882a593Smuzhiyun struct drm_bridge_state *old_bridge_state)
774*4882a593Smuzhiyun {
775*4882a593Smuzhiyun struct mtk_dsi *dsi = bridge_to_dsi(bridge);
776*4882a593Smuzhiyun int ret;
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun ret = mtk_dsi_poweron(dsi);
779*4882a593Smuzhiyun if (ret < 0)
780*4882a593Smuzhiyun DRM_ERROR("failed to power on dsi\n");
781*4882a593Smuzhiyun }
782*4882a593Smuzhiyun
mtk_dsi_bridge_atomic_post_disable(struct drm_bridge * bridge,struct drm_bridge_state * old_bridge_state)783*4882a593Smuzhiyun static void mtk_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
784*4882a593Smuzhiyun struct drm_bridge_state *old_bridge_state)
785*4882a593Smuzhiyun {
786*4882a593Smuzhiyun struct mtk_dsi *dsi = bridge_to_dsi(bridge);
787*4882a593Smuzhiyun
788*4882a593Smuzhiyun mtk_dsi_poweroff(dsi);
789*4882a593Smuzhiyun }
790*4882a593Smuzhiyun
791*4882a593Smuzhiyun static const struct drm_bridge_funcs mtk_dsi_bridge_funcs = {
792*4882a593Smuzhiyun .attach = mtk_dsi_bridge_attach,
793*4882a593Smuzhiyun .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
794*4882a593Smuzhiyun .atomic_disable = mtk_dsi_bridge_atomic_disable,
795*4882a593Smuzhiyun .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
796*4882a593Smuzhiyun .atomic_enable = mtk_dsi_bridge_atomic_enable,
797*4882a593Smuzhiyun .atomic_pre_enable = mtk_dsi_bridge_atomic_pre_enable,
798*4882a593Smuzhiyun .atomic_post_disable = mtk_dsi_bridge_atomic_post_disable,
799*4882a593Smuzhiyun .atomic_reset = drm_atomic_helper_bridge_reset,
800*4882a593Smuzhiyun .mode_set = mtk_dsi_bridge_mode_set,
801*4882a593Smuzhiyun };
802*4882a593Smuzhiyun
mtk_dsi_ddp_start(struct mtk_ddp_comp * comp)803*4882a593Smuzhiyun static void mtk_dsi_ddp_start(struct mtk_ddp_comp *comp)
804*4882a593Smuzhiyun {
805*4882a593Smuzhiyun struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
806*4882a593Smuzhiyun
807*4882a593Smuzhiyun mtk_dsi_poweron(dsi);
808*4882a593Smuzhiyun }
809*4882a593Smuzhiyun
mtk_dsi_ddp_stop(struct mtk_ddp_comp * comp)810*4882a593Smuzhiyun static void mtk_dsi_ddp_stop(struct mtk_ddp_comp *comp)
811*4882a593Smuzhiyun {
812*4882a593Smuzhiyun struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
813*4882a593Smuzhiyun
814*4882a593Smuzhiyun mtk_dsi_poweroff(dsi);
815*4882a593Smuzhiyun }
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun static const struct mtk_ddp_comp_funcs mtk_dsi_funcs = {
818*4882a593Smuzhiyun .start = mtk_dsi_ddp_start,
819*4882a593Smuzhiyun .stop = mtk_dsi_ddp_stop,
820*4882a593Smuzhiyun };
821*4882a593Smuzhiyun
mtk_dsi_host_attach(struct mipi_dsi_host * host,struct mipi_dsi_device * device)822*4882a593Smuzhiyun static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
823*4882a593Smuzhiyun struct mipi_dsi_device *device)
824*4882a593Smuzhiyun {
825*4882a593Smuzhiyun struct mtk_dsi *dsi = host_to_dsi(host);
826*4882a593Smuzhiyun
827*4882a593Smuzhiyun dsi->lanes = device->lanes;
828*4882a593Smuzhiyun dsi->format = device->format;
829*4882a593Smuzhiyun dsi->mode_flags = device->mode_flags;
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun return 0;
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun
mtk_dsi_wait_for_idle(struct mtk_dsi * dsi)834*4882a593Smuzhiyun static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
835*4882a593Smuzhiyun {
836*4882a593Smuzhiyun int ret;
837*4882a593Smuzhiyun u32 val;
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun ret = readl_poll_timeout(dsi->regs + DSI_INTSTA, val, !(val & DSI_BUSY),
840*4882a593Smuzhiyun 4, 2000000);
841*4882a593Smuzhiyun if (ret) {
842*4882a593Smuzhiyun DRM_WARN("polling dsi wait not busy timeout!\n");
843*4882a593Smuzhiyun
844*4882a593Smuzhiyun mtk_dsi_enable(dsi);
845*4882a593Smuzhiyun mtk_dsi_reset_engine(dsi);
846*4882a593Smuzhiyun }
847*4882a593Smuzhiyun }
848*4882a593Smuzhiyun
mtk_dsi_recv_cnt(u8 type,u8 * read_data)849*4882a593Smuzhiyun static u32 mtk_dsi_recv_cnt(u8 type, u8 *read_data)
850*4882a593Smuzhiyun {
851*4882a593Smuzhiyun switch (type) {
852*4882a593Smuzhiyun case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
853*4882a593Smuzhiyun case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
854*4882a593Smuzhiyun return 1;
855*4882a593Smuzhiyun case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
856*4882a593Smuzhiyun case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
857*4882a593Smuzhiyun return 2;
858*4882a593Smuzhiyun case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
859*4882a593Smuzhiyun case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
860*4882a593Smuzhiyun return read_data[1] + read_data[2] * 16;
861*4882a593Smuzhiyun case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
862*4882a593Smuzhiyun DRM_INFO("type is 0x02, try again\n");
863*4882a593Smuzhiyun break;
864*4882a593Smuzhiyun default:
865*4882a593Smuzhiyun DRM_INFO("type(0x%x) not recognized\n", type);
866*4882a593Smuzhiyun break;
867*4882a593Smuzhiyun }
868*4882a593Smuzhiyun
869*4882a593Smuzhiyun return 0;
870*4882a593Smuzhiyun }
871*4882a593Smuzhiyun
mtk_dsi_cmdq(struct mtk_dsi * dsi,const struct mipi_dsi_msg * msg)872*4882a593Smuzhiyun static void mtk_dsi_cmdq(struct mtk_dsi *dsi, const struct mipi_dsi_msg *msg)
873*4882a593Smuzhiyun {
874*4882a593Smuzhiyun const char *tx_buf = msg->tx_buf;
875*4882a593Smuzhiyun u8 config, cmdq_size, cmdq_off, type = msg->type;
876*4882a593Smuzhiyun u32 reg_val, cmdq_mask, i;
877*4882a593Smuzhiyun u32 reg_cmdq_off = dsi->driver_data->reg_cmdq_off;
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun if (MTK_DSI_HOST_IS_READ(type))
880*4882a593Smuzhiyun config = BTA;
881*4882a593Smuzhiyun else
882*4882a593Smuzhiyun config = (msg->tx_len > 2) ? LONG_PACKET : SHORT_PACKET;
883*4882a593Smuzhiyun
884*4882a593Smuzhiyun if (msg->tx_len > 2) {
885*4882a593Smuzhiyun cmdq_size = 1 + (msg->tx_len + 3) / 4;
886*4882a593Smuzhiyun cmdq_off = 4;
887*4882a593Smuzhiyun cmdq_mask = CONFIG | DATA_ID | DATA_0 | DATA_1;
888*4882a593Smuzhiyun reg_val = (msg->tx_len << 16) | (type << 8) | config;
889*4882a593Smuzhiyun } else {
890*4882a593Smuzhiyun cmdq_size = 1;
891*4882a593Smuzhiyun cmdq_off = 2;
892*4882a593Smuzhiyun cmdq_mask = CONFIG | DATA_ID;
893*4882a593Smuzhiyun reg_val = (type << 8) | config;
894*4882a593Smuzhiyun }
895*4882a593Smuzhiyun
896*4882a593Smuzhiyun for (i = 0; i < msg->tx_len; i++)
897*4882a593Smuzhiyun mtk_dsi_mask(dsi, (reg_cmdq_off + cmdq_off + i) & (~0x3U),
898*4882a593Smuzhiyun (0xffUL << (((i + cmdq_off) & 3U) * 8U)),
899*4882a593Smuzhiyun tx_buf[i] << (((i + cmdq_off) & 3U) * 8U));
900*4882a593Smuzhiyun
901*4882a593Smuzhiyun mtk_dsi_mask(dsi, reg_cmdq_off, cmdq_mask, reg_val);
902*4882a593Smuzhiyun mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE, cmdq_size);
903*4882a593Smuzhiyun }
904*4882a593Smuzhiyun
mtk_dsi_host_send_cmd(struct mtk_dsi * dsi,const struct mipi_dsi_msg * msg,u8 flag)905*4882a593Smuzhiyun static ssize_t mtk_dsi_host_send_cmd(struct mtk_dsi *dsi,
906*4882a593Smuzhiyun const struct mipi_dsi_msg *msg, u8 flag)
907*4882a593Smuzhiyun {
908*4882a593Smuzhiyun mtk_dsi_wait_for_idle(dsi);
909*4882a593Smuzhiyun mtk_dsi_irq_data_clear(dsi, flag);
910*4882a593Smuzhiyun mtk_dsi_cmdq(dsi, msg);
911*4882a593Smuzhiyun mtk_dsi_start(dsi);
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun if (!mtk_dsi_wait_for_irq_done(dsi, flag, 2000))
914*4882a593Smuzhiyun return -ETIME;
915*4882a593Smuzhiyun else
916*4882a593Smuzhiyun return 0;
917*4882a593Smuzhiyun }
918*4882a593Smuzhiyun
mtk_dsi_host_transfer(struct mipi_dsi_host * host,const struct mipi_dsi_msg * msg)919*4882a593Smuzhiyun static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
920*4882a593Smuzhiyun const struct mipi_dsi_msg *msg)
921*4882a593Smuzhiyun {
922*4882a593Smuzhiyun struct mtk_dsi *dsi = host_to_dsi(host);
923*4882a593Smuzhiyun u32 recv_cnt, i;
924*4882a593Smuzhiyun u8 read_data[16];
925*4882a593Smuzhiyun void *src_addr;
926*4882a593Smuzhiyun u8 irq_flag = CMD_DONE_INT_FLAG;
927*4882a593Smuzhiyun u32 dsi_mode;
928*4882a593Smuzhiyun int ret;
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun dsi_mode = readl(dsi->regs + DSI_MODE_CTRL);
931*4882a593Smuzhiyun if (dsi_mode & MODE) {
932*4882a593Smuzhiyun mtk_dsi_stop(dsi);
933*4882a593Smuzhiyun ret = mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, 500);
934*4882a593Smuzhiyun if (ret)
935*4882a593Smuzhiyun goto restore_dsi_mode;
936*4882a593Smuzhiyun }
937*4882a593Smuzhiyun
938*4882a593Smuzhiyun if (MTK_DSI_HOST_IS_READ(msg->type))
939*4882a593Smuzhiyun irq_flag |= LPRX_RD_RDY_INT_FLAG;
940*4882a593Smuzhiyun
941*4882a593Smuzhiyun mtk_dsi_lane_ready(dsi);
942*4882a593Smuzhiyun
943*4882a593Smuzhiyun ret = mtk_dsi_host_send_cmd(dsi, msg, irq_flag);
944*4882a593Smuzhiyun if (ret)
945*4882a593Smuzhiyun goto restore_dsi_mode;
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun if (!MTK_DSI_HOST_IS_READ(msg->type)) {
948*4882a593Smuzhiyun recv_cnt = 0;
949*4882a593Smuzhiyun goto restore_dsi_mode;
950*4882a593Smuzhiyun }
951*4882a593Smuzhiyun
952*4882a593Smuzhiyun if (!msg->rx_buf) {
953*4882a593Smuzhiyun DRM_ERROR("dsi receive buffer size may be NULL\n");
954*4882a593Smuzhiyun ret = -EINVAL;
955*4882a593Smuzhiyun goto restore_dsi_mode;
956*4882a593Smuzhiyun }
957*4882a593Smuzhiyun
958*4882a593Smuzhiyun for (i = 0; i < 16; i++)
959*4882a593Smuzhiyun *(read_data + i) = readb(dsi->regs + DSI_RX_DATA0 + i);
960*4882a593Smuzhiyun
961*4882a593Smuzhiyun recv_cnt = mtk_dsi_recv_cnt(read_data[0], read_data);
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun if (recv_cnt > 2)
964*4882a593Smuzhiyun src_addr = &read_data[4];
965*4882a593Smuzhiyun else
966*4882a593Smuzhiyun src_addr = &read_data[1];
967*4882a593Smuzhiyun
968*4882a593Smuzhiyun if (recv_cnt > 10)
969*4882a593Smuzhiyun recv_cnt = 10;
970*4882a593Smuzhiyun
971*4882a593Smuzhiyun if (recv_cnt > msg->rx_len)
972*4882a593Smuzhiyun recv_cnt = msg->rx_len;
973*4882a593Smuzhiyun
974*4882a593Smuzhiyun if (recv_cnt)
975*4882a593Smuzhiyun memcpy(msg->rx_buf, src_addr, recv_cnt);
976*4882a593Smuzhiyun
977*4882a593Smuzhiyun DRM_INFO("dsi get %d byte data from the panel address(0x%x)\n",
978*4882a593Smuzhiyun recv_cnt, *((u8 *)(msg->tx_buf)));
979*4882a593Smuzhiyun
980*4882a593Smuzhiyun restore_dsi_mode:
981*4882a593Smuzhiyun if (dsi_mode & MODE) {
982*4882a593Smuzhiyun mtk_dsi_set_mode(dsi);
983*4882a593Smuzhiyun mtk_dsi_start(dsi);
984*4882a593Smuzhiyun }
985*4882a593Smuzhiyun
986*4882a593Smuzhiyun return ret < 0 ? ret : recv_cnt;
987*4882a593Smuzhiyun }
988*4882a593Smuzhiyun
989*4882a593Smuzhiyun static const struct mipi_dsi_host_ops mtk_dsi_ops = {
990*4882a593Smuzhiyun .attach = mtk_dsi_host_attach,
991*4882a593Smuzhiyun .transfer = mtk_dsi_host_transfer,
992*4882a593Smuzhiyun };
993*4882a593Smuzhiyun
mtk_dsi_encoder_init(struct drm_device * drm,struct mtk_dsi * dsi)994*4882a593Smuzhiyun static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
995*4882a593Smuzhiyun {
996*4882a593Smuzhiyun int ret;
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun ret = drm_simple_encoder_init(drm, &dsi->encoder,
999*4882a593Smuzhiyun DRM_MODE_ENCODER_DSI);
1000*4882a593Smuzhiyun if (ret) {
1001*4882a593Smuzhiyun DRM_ERROR("Failed to encoder init to drm\n");
1002*4882a593Smuzhiyun return ret;
1003*4882a593Smuzhiyun }
1004*4882a593Smuzhiyun
1005*4882a593Smuzhiyun dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->ddp_comp);
1006*4882a593Smuzhiyun
1007*4882a593Smuzhiyun ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
1008*4882a593Smuzhiyun DRM_BRIDGE_ATTACH_NO_CONNECTOR);
1009*4882a593Smuzhiyun if (ret)
1010*4882a593Smuzhiyun goto err_cleanup_encoder;
1011*4882a593Smuzhiyun
1012*4882a593Smuzhiyun dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
1013*4882a593Smuzhiyun if (IS_ERR(dsi->connector)) {
1014*4882a593Smuzhiyun DRM_ERROR("Unable to create bridge connector\n");
1015*4882a593Smuzhiyun ret = PTR_ERR(dsi->connector);
1016*4882a593Smuzhiyun goto err_cleanup_encoder;
1017*4882a593Smuzhiyun }
1018*4882a593Smuzhiyun drm_connector_attach_encoder(dsi->connector, &dsi->encoder);
1019*4882a593Smuzhiyun
1020*4882a593Smuzhiyun return 0;
1021*4882a593Smuzhiyun
1022*4882a593Smuzhiyun err_cleanup_encoder:
1023*4882a593Smuzhiyun drm_encoder_cleanup(&dsi->encoder);
1024*4882a593Smuzhiyun return ret;
1025*4882a593Smuzhiyun }
1026*4882a593Smuzhiyun
mtk_dsi_bind(struct device * dev,struct device * master,void * data)1027*4882a593Smuzhiyun static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
1028*4882a593Smuzhiyun {
1029*4882a593Smuzhiyun int ret;
1030*4882a593Smuzhiyun struct drm_device *drm = data;
1031*4882a593Smuzhiyun struct mtk_dsi *dsi = dev_get_drvdata(dev);
1032*4882a593Smuzhiyun
1033*4882a593Smuzhiyun ret = mtk_ddp_comp_register(drm, &dsi->ddp_comp);
1034*4882a593Smuzhiyun if (ret < 0) {
1035*4882a593Smuzhiyun dev_err(dev, "Failed to register component %pOF: %d\n",
1036*4882a593Smuzhiyun dev->of_node, ret);
1037*4882a593Smuzhiyun return ret;
1038*4882a593Smuzhiyun }
1039*4882a593Smuzhiyun
1040*4882a593Smuzhiyun ret = mtk_dsi_encoder_init(drm, dsi);
1041*4882a593Smuzhiyun if (ret)
1042*4882a593Smuzhiyun goto err_unregister;
1043*4882a593Smuzhiyun
1044*4882a593Smuzhiyun return 0;
1045*4882a593Smuzhiyun
1046*4882a593Smuzhiyun err_unregister:
1047*4882a593Smuzhiyun mtk_ddp_comp_unregister(drm, &dsi->ddp_comp);
1048*4882a593Smuzhiyun return ret;
1049*4882a593Smuzhiyun }
1050*4882a593Smuzhiyun
mtk_dsi_unbind(struct device * dev,struct device * master,void * data)1051*4882a593Smuzhiyun static void mtk_dsi_unbind(struct device *dev, struct device *master,
1052*4882a593Smuzhiyun void *data)
1053*4882a593Smuzhiyun {
1054*4882a593Smuzhiyun struct drm_device *drm = data;
1055*4882a593Smuzhiyun struct mtk_dsi *dsi = dev_get_drvdata(dev);
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun drm_encoder_cleanup(&dsi->encoder);
1058*4882a593Smuzhiyun mtk_ddp_comp_unregister(drm, &dsi->ddp_comp);
1059*4882a593Smuzhiyun }
1060*4882a593Smuzhiyun
1061*4882a593Smuzhiyun static const struct component_ops mtk_dsi_component_ops = {
1062*4882a593Smuzhiyun .bind = mtk_dsi_bind,
1063*4882a593Smuzhiyun .unbind = mtk_dsi_unbind,
1064*4882a593Smuzhiyun };
1065*4882a593Smuzhiyun
mtk_dsi_probe(struct platform_device * pdev)1066*4882a593Smuzhiyun static int mtk_dsi_probe(struct platform_device *pdev)
1067*4882a593Smuzhiyun {
1068*4882a593Smuzhiyun struct mtk_dsi *dsi;
1069*4882a593Smuzhiyun struct device *dev = &pdev->dev;
1070*4882a593Smuzhiyun struct drm_panel *panel;
1071*4882a593Smuzhiyun struct resource *regs;
1072*4882a593Smuzhiyun int irq_num;
1073*4882a593Smuzhiyun int comp_id;
1074*4882a593Smuzhiyun int ret;
1075*4882a593Smuzhiyun
1076*4882a593Smuzhiyun dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
1077*4882a593Smuzhiyun if (!dsi)
1078*4882a593Smuzhiyun return -ENOMEM;
1079*4882a593Smuzhiyun
1080*4882a593Smuzhiyun dsi->host.ops = &mtk_dsi_ops;
1081*4882a593Smuzhiyun dsi->host.dev = dev;
1082*4882a593Smuzhiyun ret = mipi_dsi_host_register(&dsi->host);
1083*4882a593Smuzhiyun if (ret < 0) {
1084*4882a593Smuzhiyun dev_err(dev, "failed to register DSI host: %d\n", ret);
1085*4882a593Smuzhiyun return ret;
1086*4882a593Smuzhiyun }
1087*4882a593Smuzhiyun
1088*4882a593Smuzhiyun ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
1089*4882a593Smuzhiyun &panel, &dsi->next_bridge);
1090*4882a593Smuzhiyun if (ret)
1091*4882a593Smuzhiyun goto err_unregister_host;
1092*4882a593Smuzhiyun
1093*4882a593Smuzhiyun if (panel) {
1094*4882a593Smuzhiyun dsi->next_bridge = devm_drm_panel_bridge_add(dev, panel);
1095*4882a593Smuzhiyun if (IS_ERR(dsi->next_bridge)) {
1096*4882a593Smuzhiyun ret = PTR_ERR(dsi->next_bridge);
1097*4882a593Smuzhiyun goto err_unregister_host;
1098*4882a593Smuzhiyun }
1099*4882a593Smuzhiyun }
1100*4882a593Smuzhiyun
1101*4882a593Smuzhiyun dsi->driver_data = of_device_get_match_data(dev);
1102*4882a593Smuzhiyun
1103*4882a593Smuzhiyun dsi->engine_clk = devm_clk_get(dev, "engine");
1104*4882a593Smuzhiyun if (IS_ERR(dsi->engine_clk)) {
1105*4882a593Smuzhiyun ret = PTR_ERR(dsi->engine_clk);
1106*4882a593Smuzhiyun
1107*4882a593Smuzhiyun if (ret != -EPROBE_DEFER)
1108*4882a593Smuzhiyun dev_err(dev, "Failed to get engine clock: %d\n", ret);
1109*4882a593Smuzhiyun goto err_unregister_host;
1110*4882a593Smuzhiyun }
1111*4882a593Smuzhiyun
1112*4882a593Smuzhiyun dsi->digital_clk = devm_clk_get(dev, "digital");
1113*4882a593Smuzhiyun if (IS_ERR(dsi->digital_clk)) {
1114*4882a593Smuzhiyun ret = PTR_ERR(dsi->digital_clk);
1115*4882a593Smuzhiyun
1116*4882a593Smuzhiyun if (ret != -EPROBE_DEFER)
1117*4882a593Smuzhiyun dev_err(dev, "Failed to get digital clock: %d\n", ret);
1118*4882a593Smuzhiyun goto err_unregister_host;
1119*4882a593Smuzhiyun }
1120*4882a593Smuzhiyun
1121*4882a593Smuzhiyun dsi->hs_clk = devm_clk_get(dev, "hs");
1122*4882a593Smuzhiyun if (IS_ERR(dsi->hs_clk)) {
1123*4882a593Smuzhiyun ret = PTR_ERR(dsi->hs_clk);
1124*4882a593Smuzhiyun dev_err(dev, "Failed to get hs clock: %d\n", ret);
1125*4882a593Smuzhiyun goto err_unregister_host;
1126*4882a593Smuzhiyun }
1127*4882a593Smuzhiyun
1128*4882a593Smuzhiyun regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1129*4882a593Smuzhiyun dsi->regs = devm_ioremap_resource(dev, regs);
1130*4882a593Smuzhiyun if (IS_ERR(dsi->regs)) {
1131*4882a593Smuzhiyun ret = PTR_ERR(dsi->regs);
1132*4882a593Smuzhiyun dev_err(dev, "Failed to ioremap memory: %d\n", ret);
1133*4882a593Smuzhiyun goto err_unregister_host;
1134*4882a593Smuzhiyun }
1135*4882a593Smuzhiyun
1136*4882a593Smuzhiyun dsi->phy = devm_phy_get(dev, "dphy");
1137*4882a593Smuzhiyun if (IS_ERR(dsi->phy)) {
1138*4882a593Smuzhiyun ret = PTR_ERR(dsi->phy);
1139*4882a593Smuzhiyun dev_err(dev, "Failed to get MIPI-DPHY: %d\n", ret);
1140*4882a593Smuzhiyun goto err_unregister_host;
1141*4882a593Smuzhiyun }
1142*4882a593Smuzhiyun
1143*4882a593Smuzhiyun comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DSI);
1144*4882a593Smuzhiyun if (comp_id < 0) {
1145*4882a593Smuzhiyun dev_err(dev, "Failed to identify by alias: %d\n", comp_id);
1146*4882a593Smuzhiyun ret = comp_id;
1147*4882a593Smuzhiyun goto err_unregister_host;
1148*4882a593Smuzhiyun }
1149*4882a593Smuzhiyun
1150*4882a593Smuzhiyun ret = mtk_ddp_comp_init(dev, dev->of_node, &dsi->ddp_comp, comp_id,
1151*4882a593Smuzhiyun &mtk_dsi_funcs);
1152*4882a593Smuzhiyun if (ret) {
1153*4882a593Smuzhiyun dev_err(dev, "Failed to initialize component: %d\n", ret);
1154*4882a593Smuzhiyun goto err_unregister_host;
1155*4882a593Smuzhiyun }
1156*4882a593Smuzhiyun
1157*4882a593Smuzhiyun irq_num = platform_get_irq(pdev, 0);
1158*4882a593Smuzhiyun if (irq_num < 0) {
1159*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to get dsi irq_num: %d\n", irq_num);
1160*4882a593Smuzhiyun ret = irq_num;
1161*4882a593Smuzhiyun goto err_unregister_host;
1162*4882a593Smuzhiyun }
1163*4882a593Smuzhiyun
1164*4882a593Smuzhiyun irq_set_status_flags(irq_num, IRQ_TYPE_LEVEL_LOW);
1165*4882a593Smuzhiyun ret = devm_request_irq(&pdev->dev, irq_num, mtk_dsi_irq,
1166*4882a593Smuzhiyun IRQF_TRIGGER_LOW, dev_name(&pdev->dev), dsi);
1167*4882a593Smuzhiyun if (ret) {
1168*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to request mediatek dsi irq\n");
1169*4882a593Smuzhiyun goto err_unregister_host;
1170*4882a593Smuzhiyun }
1171*4882a593Smuzhiyun
1172*4882a593Smuzhiyun init_waitqueue_head(&dsi->irq_wait_queue);
1173*4882a593Smuzhiyun
1174*4882a593Smuzhiyun platform_set_drvdata(pdev, dsi);
1175*4882a593Smuzhiyun
1176*4882a593Smuzhiyun dsi->bridge.funcs = &mtk_dsi_bridge_funcs;
1177*4882a593Smuzhiyun dsi->bridge.of_node = dev->of_node;
1178*4882a593Smuzhiyun dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
1179*4882a593Smuzhiyun
1180*4882a593Smuzhiyun drm_bridge_add(&dsi->bridge);
1181*4882a593Smuzhiyun
1182*4882a593Smuzhiyun ret = component_add(&pdev->dev, &mtk_dsi_component_ops);
1183*4882a593Smuzhiyun if (ret) {
1184*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to add component: %d\n", ret);
1185*4882a593Smuzhiyun goto err_unregister_host;
1186*4882a593Smuzhiyun }
1187*4882a593Smuzhiyun
1188*4882a593Smuzhiyun return 0;
1189*4882a593Smuzhiyun
1190*4882a593Smuzhiyun err_unregister_host:
1191*4882a593Smuzhiyun mipi_dsi_host_unregister(&dsi->host);
1192*4882a593Smuzhiyun return ret;
1193*4882a593Smuzhiyun }
1194*4882a593Smuzhiyun
mtk_dsi_remove(struct platform_device * pdev)1195*4882a593Smuzhiyun static int mtk_dsi_remove(struct platform_device *pdev)
1196*4882a593Smuzhiyun {
1197*4882a593Smuzhiyun struct mtk_dsi *dsi = platform_get_drvdata(pdev);
1198*4882a593Smuzhiyun
1199*4882a593Smuzhiyun mtk_output_dsi_disable(dsi);
1200*4882a593Smuzhiyun drm_bridge_remove(&dsi->bridge);
1201*4882a593Smuzhiyun component_del(&pdev->dev, &mtk_dsi_component_ops);
1202*4882a593Smuzhiyun mipi_dsi_host_unregister(&dsi->host);
1203*4882a593Smuzhiyun
1204*4882a593Smuzhiyun return 0;
1205*4882a593Smuzhiyun }
1206*4882a593Smuzhiyun
1207*4882a593Smuzhiyun static const struct mtk_dsi_driver_data mt8173_dsi_driver_data = {
1208*4882a593Smuzhiyun .reg_cmdq_off = 0x200,
1209*4882a593Smuzhiyun };
1210*4882a593Smuzhiyun
1211*4882a593Smuzhiyun static const struct mtk_dsi_driver_data mt2701_dsi_driver_data = {
1212*4882a593Smuzhiyun .reg_cmdq_off = 0x180,
1213*4882a593Smuzhiyun };
1214*4882a593Smuzhiyun
1215*4882a593Smuzhiyun static const struct mtk_dsi_driver_data mt8183_dsi_driver_data = {
1216*4882a593Smuzhiyun .reg_cmdq_off = 0x200,
1217*4882a593Smuzhiyun .has_shadow_ctl = true,
1218*4882a593Smuzhiyun .has_size_ctl = true,
1219*4882a593Smuzhiyun };
1220*4882a593Smuzhiyun
1221*4882a593Smuzhiyun static const struct of_device_id mtk_dsi_of_match[] = {
1222*4882a593Smuzhiyun { .compatible = "mediatek,mt2701-dsi",
1223*4882a593Smuzhiyun .data = &mt2701_dsi_driver_data },
1224*4882a593Smuzhiyun { .compatible = "mediatek,mt8173-dsi",
1225*4882a593Smuzhiyun .data = &mt8173_dsi_driver_data },
1226*4882a593Smuzhiyun { .compatible = "mediatek,mt8183-dsi",
1227*4882a593Smuzhiyun .data = &mt8183_dsi_driver_data },
1228*4882a593Smuzhiyun { },
1229*4882a593Smuzhiyun };
1230*4882a593Smuzhiyun
1231*4882a593Smuzhiyun struct platform_driver mtk_dsi_driver = {
1232*4882a593Smuzhiyun .probe = mtk_dsi_probe,
1233*4882a593Smuzhiyun .remove = mtk_dsi_remove,
1234*4882a593Smuzhiyun .driver = {
1235*4882a593Smuzhiyun .name = "mtk-dsi",
1236*4882a593Smuzhiyun .of_match_table = mtk_dsi_of_match,
1237*4882a593Smuzhiyun },
1238*4882a593Smuzhiyun };
1239