Commit 095db161b236ba398de79691937d7fb63bd498be
1 parent
9c4609783e
Exists in
smarc_8mm_imx_4.14.98_2.0.0_ga
and in
4 other branches
MLK-21150-2 drm/bridge: sec-dsim: refine hblank word count compute
When there is no existing horizontal blanking word counts in 'dsim_hblank_par' tables, these data requires to be computed according to the 'hfp', 'hbp' and 'hsa' timings which are in pixel unit. So the pixel unit data requires to be converted to word count unit data correctly to match the PLL output clk frequency. Signed-off-by: Fancy Fang <chen.fang@nxp.com> (cherry picked from commit af9ab0d4362d9298978e2ac62033f65ea1cc09ed)
Showing 1 changed file with 19 additions and 6 deletions Inline Diff
drivers/gpu/drm/bridge/sec-dsim.c
1 | /* | 1 | /* |
2 | * Samsung MIPI DSIM Bridge | 2 | * Samsung MIPI DSIM Bridge |
3 | * | 3 | * |
4 | * Copyright 2018-2019 NXP | 4 | * Copyright 2018-2019 NXP |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; either version 2 of the License, or | 8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. | 9 | * (at your option) any later version. |
10 | * | 10 | * |
11 | * This program is distributed in the hope that it will be useful, | 11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | 14 | * GNU General Public License for more details. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <asm/unaligned.h> | 17 | #include <asm/unaligned.h> |
18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
19 | #include <linux/completion.h> | 19 | #include <linux/completion.h> |
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/of_graph.h> | 22 | #include <linux/of_graph.h> |
23 | #include <drm/bridge/sec_mipi_dsim.h> | 23 | #include <drm/bridge/sec_mipi_dsim.h> |
24 | #include <drm/drmP.h> | 24 | #include <drm/drmP.h> |
25 | #include <drm/drm_atomic_helper.h> | 25 | #include <drm/drm_atomic_helper.h> |
26 | #include <drm/drm_bridge.h> | 26 | #include <drm/drm_bridge.h> |
27 | #include <drm/drm_connector.h> | 27 | #include <drm/drm_connector.h> |
28 | #include <drm/drm_crtc_helper.h> | 28 | #include <drm/drm_crtc_helper.h> |
29 | #include <drm/drm_encoder.h> | 29 | #include <drm/drm_encoder.h> |
30 | #include <drm/drm_fourcc.h> | 30 | #include <drm/drm_fourcc.h> |
31 | #include <drm/drm_mipi_dsi.h> | 31 | #include <drm/drm_mipi_dsi.h> |
32 | #include <drm/drm_panel.h> | 32 | #include <drm/drm_panel.h> |
33 | #include <video/videomode.h> | 33 | #include <video/videomode.h> |
34 | #include <video/mipi_display.h> | 34 | #include <video/mipi_display.h> |
35 | 35 | ||
36 | /* dsim registers */ | 36 | /* dsim registers */ |
37 | #define DSIM_VERSION 0x00 | 37 | #define DSIM_VERSION 0x00 |
38 | #define DSIM_STATUS 0x04 | 38 | #define DSIM_STATUS 0x04 |
39 | #define DSIM_RGB_STATUS 0x08 | 39 | #define DSIM_RGB_STATUS 0x08 |
40 | #define DSIM_SWRST 0x0c | 40 | #define DSIM_SWRST 0x0c |
41 | #define DSIM_CLKCTRL 0x10 | 41 | #define DSIM_CLKCTRL 0x10 |
42 | #define DSIM_TIMEOUT 0x14 | 42 | #define DSIM_TIMEOUT 0x14 |
43 | #define DSIM_CONFIG 0x18 | 43 | #define DSIM_CONFIG 0x18 |
44 | #define DSIM_ESCMODE 0x1c | 44 | #define DSIM_ESCMODE 0x1c |
45 | #define DSIM_MDRESOL 0x20 | 45 | #define DSIM_MDRESOL 0x20 |
46 | #define DSIM_MVPORCH 0x24 | 46 | #define DSIM_MVPORCH 0x24 |
47 | #define DSIM_MHPORCH 0x28 | 47 | #define DSIM_MHPORCH 0x28 |
48 | #define DSIM_MSYNC 0x2c | 48 | #define DSIM_MSYNC 0x2c |
49 | #define DSIM_SDRESOL 0x30 | 49 | #define DSIM_SDRESOL 0x30 |
50 | #define DSIM_INTSRC 0x34 | 50 | #define DSIM_INTSRC 0x34 |
51 | #define DSIM_INTMSK 0x38 | 51 | #define DSIM_INTMSK 0x38 |
52 | 52 | ||
53 | /* packet */ | 53 | /* packet */ |
54 | #define DSIM_PKTHDR 0x3c | 54 | #define DSIM_PKTHDR 0x3c |
55 | #define DSIM_PAYLOAD 0x40 | 55 | #define DSIM_PAYLOAD 0x40 |
56 | #define DSIM_RXFIFO 0x44 | 56 | #define DSIM_RXFIFO 0x44 |
57 | #define DSIM_FIFOTHLD 0x48 | 57 | #define DSIM_FIFOTHLD 0x48 |
58 | #define DSIM_FIFOCTRL 0x4c | 58 | #define DSIM_FIFOCTRL 0x4c |
59 | #define DSIM_MEMACCHR 0x50 | 59 | #define DSIM_MEMACCHR 0x50 |
60 | #define DSIM_MULTI_PKT 0x78 | 60 | #define DSIM_MULTI_PKT 0x78 |
61 | 61 | ||
62 | /* pll control */ | 62 | /* pll control */ |
63 | #define DSIM_PLLCTRL_1G 0x90 | 63 | #define DSIM_PLLCTRL_1G 0x90 |
64 | #define DSIM_PLLCTRL 0x94 | 64 | #define DSIM_PLLCTRL 0x94 |
65 | #define DSIM_PLLCTRL1 0x98 | 65 | #define DSIM_PLLCTRL1 0x98 |
66 | #define DSIM_PLLCTRL2 0x9c | 66 | #define DSIM_PLLCTRL2 0x9c |
67 | #define DSIM_PLLTMR 0xa0 | 67 | #define DSIM_PLLTMR 0xa0 |
68 | 68 | ||
69 | /* dphy */ | 69 | /* dphy */ |
70 | #define DSIM_PHYTIMING 0xb4 | 70 | #define DSIM_PHYTIMING 0xb4 |
71 | #define DSIM_PHYTIMING1 0xb8 | 71 | #define DSIM_PHYTIMING1 0xb8 |
72 | #define DSIM_PHYTIMING2 0xbc | 72 | #define DSIM_PHYTIMING2 0xbc |
73 | 73 | ||
74 | /* reg bit manipulation */ | 74 | /* reg bit manipulation */ |
75 | #define REG_MASK(e, s) (((1 << ((e) - (s) + 1)) - 1) << (s)) | 75 | #define REG_MASK(e, s) (((1 << ((e) - (s) + 1)) - 1) << (s)) |
76 | #define REG_PUT(x, e, s) (((x) << (s)) & REG_MASK(e, s)) | 76 | #define REG_PUT(x, e, s) (((x) << (s)) & REG_MASK(e, s)) |
77 | #define REG_GET(x, e, s) (((x) & REG_MASK(e, s)) >> (s)) | 77 | #define REG_GET(x, e, s) (((x) & REG_MASK(e, s)) >> (s)) |
78 | 78 | ||
79 | /* register bit fields */ | 79 | /* register bit fields */ |
80 | #define STATUS_PLLSTABLE BIT(31) | 80 | #define STATUS_PLLSTABLE BIT(31) |
81 | #define STATUS_SWRSTRLS BIT(20) | 81 | #define STATUS_SWRSTRLS BIT(20) |
82 | #define STATUS_TXREADYHSCLK BIT(10) | 82 | #define STATUS_TXREADYHSCLK BIT(10) |
83 | #define STATUS_ULPSCLK BIT(9) | 83 | #define STATUS_ULPSCLK BIT(9) |
84 | #define STATUS_STOPSTATECLK BIT(8) | 84 | #define STATUS_STOPSTATECLK BIT(8) |
85 | #define STATUS_GET_ULPSDAT(x) REG_GET(x, 7, 4) | 85 | #define STATUS_GET_ULPSDAT(x) REG_GET(x, 7, 4) |
86 | #define STATUS_GET_STOPSTATEDAT(x) REG_GET(x, 3, 0) | 86 | #define STATUS_GET_STOPSTATEDAT(x) REG_GET(x, 3, 0) |
87 | 87 | ||
88 | #define RGB_STATUS_CMDMODE_INSEL BIT(31) | 88 | #define RGB_STATUS_CMDMODE_INSEL BIT(31) |
89 | #define RGB_STATUS_GET_RGBSTATE(x) REG_GET(x, 12, 0) | 89 | #define RGB_STATUS_GET_RGBSTATE(x) REG_GET(x, 12, 0) |
90 | 90 | ||
91 | #define CLKCTRL_TXREQUESTHSCLK BIT(31) | 91 | #define CLKCTRL_TXREQUESTHSCLK BIT(31) |
92 | #define CLKCTRL_DPHY_SEL_1G BIT(29) | 92 | #define CLKCTRL_DPHY_SEL_1G BIT(29) |
93 | #define CLKCTRL_DPHY_SEL_1P5G (0x0 << 29) | 93 | #define CLKCTRL_DPHY_SEL_1P5G (0x0 << 29) |
94 | #define CLKCTRL_ESCCLKEN BIT(28) | 94 | #define CLKCTRL_ESCCLKEN BIT(28) |
95 | #define CLKCTRL_PLLBYPASS BIT(29) | 95 | #define CLKCTRL_PLLBYPASS BIT(29) |
96 | #define CLKCTRL_BYTECLKSRC_DPHY_PLL REG_PUT(0, 26, 25) | 96 | #define CLKCTRL_BYTECLKSRC_DPHY_PLL REG_PUT(0, 26, 25) |
97 | #define CLKCTRL_BYTECLKEN BIT(24) | 97 | #define CLKCTRL_BYTECLKEN BIT(24) |
98 | #define CLKCTRL_SET_LANEESCCLKEN(x) REG_PUT(x, 23, 19) | 98 | #define CLKCTRL_SET_LANEESCCLKEN(x) REG_PUT(x, 23, 19) |
99 | #define CLKCTRL_SET_ESCPRESCALER(x) REG_PUT(x, 15, 0) | 99 | #define CLKCTRL_SET_ESCPRESCALER(x) REG_PUT(x, 15, 0) |
100 | 100 | ||
101 | #define TIMEOUT_SET_BTAOUT(x) REG_PUT(x, 23, 16) | 101 | #define TIMEOUT_SET_BTAOUT(x) REG_PUT(x, 23, 16) |
102 | #define TIMEOUT_SET_LPDRTOUT(x) REG_PUT(x, 15, 0) | 102 | #define TIMEOUT_SET_LPDRTOUT(x) REG_PUT(x, 15, 0) |
103 | 103 | ||
104 | #define CONFIG_NON_CONTINUOUS_CLOCK_LANE BIT(31) | 104 | #define CONFIG_NON_CONTINUOUS_CLOCK_LANE BIT(31) |
105 | #define CONFIG_CLKLANE_STOP_START BIT(30) | 105 | #define CONFIG_CLKLANE_STOP_START BIT(30) |
106 | #define CONFIG_MFLUSH_VS BIT(29) | 106 | #define CONFIG_MFLUSH_VS BIT(29) |
107 | #define CONFIG_EOT_R03 BIT(28) | 107 | #define CONFIG_EOT_R03 BIT(28) |
108 | #define CONFIG_SYNCINFORM BIT(27) | 108 | #define CONFIG_SYNCINFORM BIT(27) |
109 | #define CONFIG_BURSTMODE BIT(26) | 109 | #define CONFIG_BURSTMODE BIT(26) |
110 | #define CONFIG_VIDEOMODE BIT(25) | 110 | #define CONFIG_VIDEOMODE BIT(25) |
111 | #define CONFIG_AUTOMODE BIT(24) | 111 | #define CONFIG_AUTOMODE BIT(24) |
112 | #define CONFIG_HSEDISABLEMODE BIT(23) | 112 | #define CONFIG_HSEDISABLEMODE BIT(23) |
113 | #define CONFIG_HFPDISABLEMODE BIT(22) | 113 | #define CONFIG_HFPDISABLEMODE BIT(22) |
114 | #define CONFIG_HBPDISABLEMODE BIT(21) | 114 | #define CONFIG_HBPDISABLEMODE BIT(21) |
115 | #define CONFIG_HSADISABLEMODE BIT(20) | 115 | #define CONFIG_HSADISABLEMODE BIT(20) |
116 | #define CONFIG_SET_MAINVC(x) REG_PUT(x, 19, 18) | 116 | #define CONFIG_SET_MAINVC(x) REG_PUT(x, 19, 18) |
117 | #define CONFIG_SET_SUBVC(x) REG_PUT(x, 17, 16) | 117 | #define CONFIG_SET_SUBVC(x) REG_PUT(x, 17, 16) |
118 | #define CONFIG_SET_MAINPIXFORMAT(x) REG_PUT(x, 14, 12) | 118 | #define CONFIG_SET_MAINPIXFORMAT(x) REG_PUT(x, 14, 12) |
119 | #define CONFIG_SET_SUBPIXFORMAT(x) REG_PUT(x, 10, 8) | 119 | #define CONFIG_SET_SUBPIXFORMAT(x) REG_PUT(x, 10, 8) |
120 | #define CONFIG_SET_NUMOFDATLANE(x) REG_PUT(x, 6, 5) | 120 | #define CONFIG_SET_NUMOFDATLANE(x) REG_PUT(x, 6, 5) |
121 | #define CONFIG_SET_LANEEN(x) REG_PUT(x, 4, 0) | 121 | #define CONFIG_SET_LANEEN(x) REG_PUT(x, 4, 0) |
122 | 122 | ||
123 | #define ESCMODE_SET_STOPSTATE_CNT(X) REG_PUT(x, 31, 21) | 123 | #define ESCMODE_SET_STOPSTATE_CNT(X) REG_PUT(x, 31, 21) |
124 | #define ESCMODE_FORCESTOPSTATE BIT(20) | 124 | #define ESCMODE_FORCESTOPSTATE BIT(20) |
125 | #define ESCMODE_FORCEBTA BIT(16) | 125 | #define ESCMODE_FORCEBTA BIT(16) |
126 | #define ESCMODE_CMDLPDT BIT(7) | 126 | #define ESCMODE_CMDLPDT BIT(7) |
127 | #define ESCMODE_TXLPDT BIT(6) | 127 | #define ESCMODE_TXLPDT BIT(6) |
128 | #define ESCMODE_TXTRIGGERRST BIT(5) | 128 | #define ESCMODE_TXTRIGGERRST BIT(5) |
129 | 129 | ||
130 | #define MDRESOL_MAINSTANDBY BIT(31) | 130 | #define MDRESOL_MAINSTANDBY BIT(31) |
131 | #define MDRESOL_SET_MAINVRESOL(x) REG_PUT(x, 27, 16) | 131 | #define MDRESOL_SET_MAINVRESOL(x) REG_PUT(x, 27, 16) |
132 | #define MDRESOL_SET_MAINHRESOL(x) REG_PUT(x, 11, 0) | 132 | #define MDRESOL_SET_MAINHRESOL(x) REG_PUT(x, 11, 0) |
133 | 133 | ||
134 | #define MVPORCH_SET_CMDALLOW(x) REG_PUT(x, 31, 28) | 134 | #define MVPORCH_SET_CMDALLOW(x) REG_PUT(x, 31, 28) |
135 | #define MVPORCH_SET_STABLEVFP(x) REG_PUT(x, 26, 16) | 135 | #define MVPORCH_SET_STABLEVFP(x) REG_PUT(x, 26, 16) |
136 | #define MVPORCH_SET_MAINVBP(x) REG_PUT(x, 10, 0) | 136 | #define MVPORCH_SET_MAINVBP(x) REG_PUT(x, 10, 0) |
137 | 137 | ||
138 | #define MHPORCH_SET_MAINHFP(x) REG_PUT(x, 31, 16) | 138 | #define MHPORCH_SET_MAINHFP(x) REG_PUT(x, 31, 16) |
139 | #define MHPORCH_SET_MAINHBP(x) REG_PUT(x, 15, 0) | 139 | #define MHPORCH_SET_MAINHBP(x) REG_PUT(x, 15, 0) |
140 | 140 | ||
141 | #define MSYNC_SET_MAINVSA(x) REG_PUT(x, 31, 22) | 141 | #define MSYNC_SET_MAINVSA(x) REG_PUT(x, 31, 22) |
142 | #define MSYNC_SET_MAINHSA(x) REG_PUT(x, 15, 0) | 142 | #define MSYNC_SET_MAINHSA(x) REG_PUT(x, 15, 0) |
143 | 143 | ||
144 | #define INTSRC_PLLSTABLE BIT(31) | 144 | #define INTSRC_PLLSTABLE BIT(31) |
145 | #define INTSRC_SWRSTRELEASE BIT(30) | 145 | #define INTSRC_SWRSTRELEASE BIT(30) |
146 | #define INTSRC_SFRPLFIFOEMPTY BIT(29) | 146 | #define INTSRC_SFRPLFIFOEMPTY BIT(29) |
147 | #define INTSRC_SFRPHFIFOEMPTY BIT(28) | 147 | #define INTSRC_SFRPHFIFOEMPTY BIT(28) |
148 | #define INTSRC_FRAMEDONE BIT(24) | 148 | #define INTSRC_FRAMEDONE BIT(24) |
149 | #define INTSRC_LPDRTOUT BIT(21) | 149 | #define INTSRC_LPDRTOUT BIT(21) |
150 | #define INTSRC_TATOUT BIT(20) | 150 | #define INTSRC_TATOUT BIT(20) |
151 | #define INTSRC_RXDATDONE BIT(18) | 151 | #define INTSRC_RXDATDONE BIT(18) |
152 | #define INTSRC_RXTE BIT(17) | 152 | #define INTSRC_RXTE BIT(17) |
153 | #define INTSRC_RXACK BIT(16) | 153 | #define INTSRC_RXACK BIT(16) |
154 | #define INTSRC_MASK (INTSRC_PLLSTABLE | \ | 154 | #define INTSRC_MASK (INTSRC_PLLSTABLE | \ |
155 | INTSRC_SWRSTRELEASE | \ | 155 | INTSRC_SWRSTRELEASE | \ |
156 | INTSRC_SFRPLFIFOEMPTY | \ | 156 | INTSRC_SFRPLFIFOEMPTY | \ |
157 | INTSRC_SFRPHFIFOEMPTY | \ | 157 | INTSRC_SFRPHFIFOEMPTY | \ |
158 | INTSRC_FRAMEDONE | \ | 158 | INTSRC_FRAMEDONE | \ |
159 | INTSRC_LPDRTOUT | \ | 159 | INTSRC_LPDRTOUT | \ |
160 | INTSRC_TATOUT | \ | 160 | INTSRC_TATOUT | \ |
161 | INTSRC_RXDATDONE | \ | 161 | INTSRC_RXDATDONE | \ |
162 | INTSRC_RXTE | \ | 162 | INTSRC_RXTE | \ |
163 | INTSRC_RXACK) | 163 | INTSRC_RXACK) |
164 | 164 | ||
165 | #define INTMSK_MSKPLLSTABLE BIT(31) | 165 | #define INTMSK_MSKPLLSTABLE BIT(31) |
166 | #define INTMSK_MSKSWRELEASE BIT(30) | 166 | #define INTMSK_MSKSWRELEASE BIT(30) |
167 | #define INTMSK_MSKSFRPLFIFOEMPTY BIT(29) | 167 | #define INTMSK_MSKSFRPLFIFOEMPTY BIT(29) |
168 | #define INTMSK_MSKSFRPHFIFOEMPTY BIT(28) | 168 | #define INTMSK_MSKSFRPHFIFOEMPTY BIT(28) |
169 | #define INTMSK_MSKFRAMEDONE BIT(24) | 169 | #define INTMSK_MSKFRAMEDONE BIT(24) |
170 | #define INTMSK_MSKLPDRTOUT BIT(21) | 170 | #define INTMSK_MSKLPDRTOUT BIT(21) |
171 | #define INTMSK_MSKTATOUT BIT(20) | 171 | #define INTMSK_MSKTATOUT BIT(20) |
172 | #define INTMSK_MSKRXDATDONE BIT(18) | 172 | #define INTMSK_MSKRXDATDONE BIT(18) |
173 | #define INTMSK_MSKRXTE BIT(17) | 173 | #define INTMSK_MSKRXTE BIT(17) |
174 | #define INTMSK_MSKRXACK BIT(16) | 174 | #define INTMSK_MSKRXACK BIT(16) |
175 | 175 | ||
176 | #define PKTHDR_SET_DATA1(x) REG_PUT(x, 23, 16) | 176 | #define PKTHDR_SET_DATA1(x) REG_PUT(x, 23, 16) |
177 | #define PKTHDR_GET_DATA1(x) REG_GET(x, 23, 16) | 177 | #define PKTHDR_GET_DATA1(x) REG_GET(x, 23, 16) |
178 | #define PKTHDR_SET_DATA0(x) REG_PUT(x, 15, 8) | 178 | #define PKTHDR_SET_DATA0(x) REG_PUT(x, 15, 8) |
179 | #define PKTHDR_GET_DATA0(x) REG_GET(x, 15, 8) | 179 | #define PKTHDR_GET_DATA0(x) REG_GET(x, 15, 8) |
180 | #define PKTHDR_GET_WC(x) REG_GET(x, 23, 8) | 180 | #define PKTHDR_GET_WC(x) REG_GET(x, 23, 8) |
181 | #define PKTHDR_SET_DI(x) REG_PUT(x, 7, 0) | 181 | #define PKTHDR_SET_DI(x) REG_PUT(x, 7, 0) |
182 | #define PKTHDR_GET_DI(x) REG_GET(x, 7, 0) | 182 | #define PKTHDR_GET_DI(x) REG_GET(x, 7, 0) |
183 | #define PKTHDR_SET_DT(x) REG_PUT(x, 5, 0) | 183 | #define PKTHDR_SET_DT(x) REG_PUT(x, 5, 0) |
184 | #define PKTHDR_GET_DT(x) REG_GET(x, 5, 0) | 184 | #define PKTHDR_GET_DT(x) REG_GET(x, 5, 0) |
185 | #define PKTHDR_SET_VC(x) REG_PUT(x, 7, 6) | 185 | #define PKTHDR_SET_VC(x) REG_PUT(x, 7, 6) |
186 | #define PKTHDR_GET_VC(x) REG_GET(x, 7, 6) | 186 | #define PKTHDR_GET_VC(x) REG_GET(x, 7, 6) |
187 | 187 | ||
188 | #define FIFOCTRL_FULLRX BIT(25) | 188 | #define FIFOCTRL_FULLRX BIT(25) |
189 | #define FIFOCTRL_EMPTYRX BIT(24) | 189 | #define FIFOCTRL_EMPTYRX BIT(24) |
190 | #define FIFOCTRL_FULLHSFR BIT(23) | 190 | #define FIFOCTRL_FULLHSFR BIT(23) |
191 | #define FIFOCTRL_EMPTYHSFR BIT(22) | 191 | #define FIFOCTRL_EMPTYHSFR BIT(22) |
192 | #define FIFOCTRL_FULLLSFR BIT(21) | 192 | #define FIFOCTRL_FULLLSFR BIT(21) |
193 | #define FIFOCTRL_EMPTYLSFR BIT(20) | 193 | #define FIFOCTRL_EMPTYLSFR BIT(20) |
194 | #define FIFOCTRL_FULLHMAIN BIT(11) | 194 | #define FIFOCTRL_FULLHMAIN BIT(11) |
195 | #define FIFOCTRL_EMPTYHMAIN BIT(10) | 195 | #define FIFOCTRL_EMPTYHMAIN BIT(10) |
196 | #define FIFOCTRL_FULLLMAIN BIT(9) | 196 | #define FIFOCTRL_FULLLMAIN BIT(9) |
197 | #define FIFOCTRL_EMPTYLMAIN BIT(8) | 197 | #define FIFOCTRL_EMPTYLMAIN BIT(8) |
198 | #define FIFOCTRL_NINITRX BIT(4) | 198 | #define FIFOCTRL_NINITRX BIT(4) |
199 | #define FIFOCTRL_NINITSFR BIT(3) | 199 | #define FIFOCTRL_NINITSFR BIT(3) |
200 | #define FIFOCTRL_NINITI80 BIT(2) | 200 | #define FIFOCTRL_NINITI80 BIT(2) |
201 | #define FIFOCTRL_NINITSUB BIT(1) | 201 | #define FIFOCTRL_NINITSUB BIT(1) |
202 | #define FIFOCTRL_NINITMAIN BIT(0) | 202 | #define FIFOCTRL_NINITMAIN BIT(0) |
203 | 203 | ||
204 | #define PLLCTRL_DPDNSWAP_CLK BIT(25) | 204 | #define PLLCTRL_DPDNSWAP_CLK BIT(25) |
205 | #define PLLCTRL_DPDNSWAP_DAT BIT(24) | 205 | #define PLLCTRL_DPDNSWAP_DAT BIT(24) |
206 | #define PLLCTRL_PLLEN BIT(23) | 206 | #define PLLCTRL_PLLEN BIT(23) |
207 | #define PLLCTRL_SET_PMS(x) REG_PUT(x, 19, 1) | 207 | #define PLLCTRL_SET_PMS(x) REG_PUT(x, 19, 1) |
208 | #define PLLCTRL_SET_P(x) REG_PUT(x, 18, 13) | 208 | #define PLLCTRL_SET_P(x) REG_PUT(x, 18, 13) |
209 | #define PLLCTRL_SET_M(x) REG_PUT(x, 12, 3) | 209 | #define PLLCTRL_SET_M(x) REG_PUT(x, 12, 3) |
210 | #define PLLCTRL_SET_S(x) REG_PUT(x, 2, 0) | 210 | #define PLLCTRL_SET_S(x) REG_PUT(x, 2, 0) |
211 | 211 | ||
212 | #define PHYTIMING_SET_M_TLPXCTL(x) REG_PUT(x, 15, 8) | 212 | #define PHYTIMING_SET_M_TLPXCTL(x) REG_PUT(x, 15, 8) |
213 | #define PHYTIMING_SET_M_THSEXITCTL(x) REG_PUT(x, 7, 0) | 213 | #define PHYTIMING_SET_M_THSEXITCTL(x) REG_PUT(x, 7, 0) |
214 | 214 | ||
215 | #define PHYTIMING1_SET_M_TCLKPRPRCTL(x) REG_PUT(x, 31, 24) | 215 | #define PHYTIMING1_SET_M_TCLKPRPRCTL(x) REG_PUT(x, 31, 24) |
216 | #define PHYTIMING1_SET_M_TCLKZEROCTL(x) REG_PUT(x, 23, 16) | 216 | #define PHYTIMING1_SET_M_TCLKZEROCTL(x) REG_PUT(x, 23, 16) |
217 | #define PHYTIMING1_SET_M_TCLKPOSTCTL(x) REG_PUT(x, 15, 8) | 217 | #define PHYTIMING1_SET_M_TCLKPOSTCTL(x) REG_PUT(x, 15, 8) |
218 | #define PHYTIMING1_SET_M_TCLKTRAILCTL(x) REG_PUT(x, 7, 0) | 218 | #define PHYTIMING1_SET_M_TCLKTRAILCTL(x) REG_PUT(x, 7, 0) |
219 | 219 | ||
220 | #define PHYTIMING2_SET_M_THSPRPRCTL(x) REG_PUT(x, 23, 16) | 220 | #define PHYTIMING2_SET_M_THSPRPRCTL(x) REG_PUT(x, 23, 16) |
221 | #define PHYTIMING2_SET_M_THSZEROCTL(x) REG_PUT(x, 15, 8) | 221 | #define PHYTIMING2_SET_M_THSZEROCTL(x) REG_PUT(x, 15, 8) |
222 | #define PHYTIMING2_SET_M_THSTRAILCTL(x) REG_PUT(x, 7, 0) | 222 | #define PHYTIMING2_SET_M_THSTRAILCTL(x) REG_PUT(x, 7, 0) |
223 | 223 | ||
224 | #define dsim_read(dsim, reg) readl(dsim->base + reg) | 224 | #define dsim_read(dsim, reg) readl(dsim->base + reg) |
225 | #define dsim_write(dsim, val, reg) writel(val, dsim->base + reg) | 225 | #define dsim_write(dsim, val, reg) writel(val, dsim->base + reg) |
226 | 226 | ||
227 | /* fixed phy ref clk rate */ | 227 | /* fixed phy ref clk rate */ |
228 | #define PHY_REF_CLK 27000000 | 228 | #define PHY_REF_CLK 27000000 |
229 | 229 | ||
230 | #define MAX_MAIN_HRESOL 2047 | 230 | #define MAX_MAIN_HRESOL 2047 |
231 | #define MAX_MAIN_VRESOL 2047 | 231 | #define MAX_MAIN_VRESOL 2047 |
232 | #define MAX_SUB_HRESOL 1024 | 232 | #define MAX_SUB_HRESOL 1024 |
233 | #define MAX_SUB_VRESOL 1024 | 233 | #define MAX_SUB_VRESOL 1024 |
234 | 234 | ||
235 | /* in KHZ */ | 235 | /* in KHZ */ |
236 | #define MAX_ESC_CLK_FREQ 20000 | 236 | #define MAX_ESC_CLK_FREQ 20000 |
237 | 237 | ||
238 | /* dsim all irqs index */ | 238 | /* dsim all irqs index */ |
239 | #define PLLSTABLE 1 | 239 | #define PLLSTABLE 1 |
240 | #define SWRSTRELEASE 2 | 240 | #define SWRSTRELEASE 2 |
241 | #define SFRPLFIFOEMPTY 3 | 241 | #define SFRPLFIFOEMPTY 3 |
242 | #define SFRPHFIFOEMPTY 4 | 242 | #define SFRPHFIFOEMPTY 4 |
243 | #define SYNCOVERRIDE 5 | 243 | #define SYNCOVERRIDE 5 |
244 | #define BUSTURNOVER 6 | 244 | #define BUSTURNOVER 6 |
245 | #define FRAMEDONE 7 | 245 | #define FRAMEDONE 7 |
246 | #define LPDRTOUT 8 | 246 | #define LPDRTOUT 8 |
247 | #define TATOUT 9 | 247 | #define TATOUT 9 |
248 | #define RXDATDONE 10 | 248 | #define RXDATDONE 10 |
249 | #define RXTE 11 | 249 | #define RXTE 11 |
250 | #define RXACK 12 | 250 | #define RXACK 12 |
251 | #define ERRRXECC 13 | 251 | #define ERRRXECC 13 |
252 | #define ERRRXCRC 14 | 252 | #define ERRRXCRC 14 |
253 | #define ERRESC3 15 | 253 | #define ERRESC3 15 |
254 | #define ERRESC2 16 | 254 | #define ERRESC2 16 |
255 | #define ERRESC1 17 | 255 | #define ERRESC1 17 |
256 | #define ERRESC0 18 | 256 | #define ERRESC0 18 |
257 | #define ERRSYNC3 19 | 257 | #define ERRSYNC3 19 |
258 | #define ERRSYNC2 20 | 258 | #define ERRSYNC2 20 |
259 | #define ERRSYNC1 21 | 259 | #define ERRSYNC1 21 |
260 | #define ERRSYNC0 22 | 260 | #define ERRSYNC0 22 |
261 | #define ERRCONTROL3 23 | 261 | #define ERRCONTROL3 23 |
262 | #define ERRCONTROL2 24 | 262 | #define ERRCONTROL2 24 |
263 | #define ERRCONTROL1 25 | 263 | #define ERRCONTROL1 25 |
264 | #define ERRCONTROL0 26 | 264 | #define ERRCONTROL0 26 |
265 | 265 | ||
266 | #define MIPI_FIFO_TIMEOUT msecs_to_jiffies(250) | 266 | #define MIPI_FIFO_TIMEOUT msecs_to_jiffies(250) |
267 | 267 | ||
268 | #define MIPI_HFP_PKT_OVERHEAD 6 | ||
269 | #define MIPI_HBP_PKT_OVERHEAD 6 | ||
270 | #define MIPI_HSA_PKT_OVERHEAD 6 | ||
271 | |||
268 | #define to_sec_mipi_dsim(dsi) container_of(dsi, struct sec_mipi_dsim, dsi_host) | 272 | #define to_sec_mipi_dsim(dsi) container_of(dsi, struct sec_mipi_dsim, dsi_host) |
269 | #define conn_to_sec_mipi_dsim(conn) \ | 273 | #define conn_to_sec_mipi_dsim(conn) \ |
270 | container_of(conn, struct sec_mipi_dsim, connector) | 274 | container_of(conn, struct sec_mipi_dsim, connector) |
271 | 275 | ||
272 | /* DSIM PLL configuration from spec: | 276 | /* DSIM PLL configuration from spec: |
273 | * | 277 | * |
274 | * Fout(DDR) = (M * Fin) / (P * 2^S), so Fout / Fin = M / (P * 2^S) | 278 | * Fout(DDR) = (M * Fin) / (P * 2^S), so Fout / Fin = M / (P * 2^S) |
275 | * Fin_pll = Fin / P (6 ~ 12 MHz) | 279 | * Fin_pll = Fin / P (6 ~ 12 MHz) |
276 | * S: [2:0], M: [12:3], P: [18:13], so | 280 | * S: [2:0], M: [12:3], P: [18:13], so |
277 | * TODO: 'S' is in [0 ~ 3], 'M' is in, 'P' is in [1 ~ 33] | 281 | * TODO: 'S' is in [0 ~ 3], 'M' is in, 'P' is in [1 ~ 33] |
278 | * | 282 | * |
279 | */ | 283 | */ |
280 | 284 | ||
281 | /* used for CEA standard modes */ | 285 | /* used for CEA standard modes */ |
282 | struct dsim_hblank_par { | 286 | struct dsim_hblank_par { |
283 | char *name; /* drm display mode name */ | 287 | char *name; /* drm display mode name */ |
284 | int vrefresh; | 288 | int vrefresh; |
285 | int hfp_wc; | 289 | int hfp_wc; |
286 | int hbp_wc; | 290 | int hbp_wc; |
287 | int hsa_wc; | 291 | int hsa_wc; |
288 | int lanes; | 292 | int lanes; |
289 | }; | 293 | }; |
290 | 294 | ||
291 | struct dsim_pll_pms { | 295 | struct dsim_pll_pms { |
292 | uint32_t bit_clk; /* kHz */ | 296 | uint32_t bit_clk; /* kHz */ |
293 | uint32_t p; | 297 | uint32_t p; |
294 | uint32_t m; | 298 | uint32_t m; |
295 | uint32_t s; | 299 | uint32_t s; |
296 | }; | 300 | }; |
297 | 301 | ||
298 | struct sec_mipi_dsim { | 302 | struct sec_mipi_dsim { |
299 | struct mipi_dsi_host dsi_host; | 303 | struct mipi_dsi_host dsi_host; |
300 | struct drm_connector connector; | 304 | struct drm_connector connector; |
301 | struct drm_encoder *encoder; | 305 | struct drm_encoder *encoder; |
302 | struct drm_bridge *bridge; | 306 | struct drm_bridge *bridge; |
303 | struct drm_bridge *next; | 307 | struct drm_bridge *next; |
304 | struct drm_panel *panel; | 308 | struct drm_panel *panel; |
305 | struct device *dev; | 309 | struct device *dev; |
306 | 310 | ||
307 | void __iomem *base; | 311 | void __iomem *base; |
308 | int irq; | 312 | int irq; |
309 | 313 | ||
310 | struct clk *clk_cfg; | 314 | struct clk *clk_cfg; |
311 | struct clk *clk_pllref; | 315 | struct clk *clk_pllref; |
312 | struct clk *pclk; /* pixel clock */ | 316 | struct clk *pclk; /* pixel clock */ |
313 | 317 | ||
314 | /* kHz clocks */ | 318 | /* kHz clocks */ |
315 | uint32_t pix_clk; | 319 | uint32_t pix_clk; |
316 | uint32_t bit_clk; | 320 | uint32_t bit_clk; |
317 | 321 | ||
318 | unsigned int lanes; | 322 | unsigned int lanes; |
319 | unsigned int channel; /* virtual channel */ | 323 | unsigned int channel; /* virtual channel */ |
320 | enum mipi_dsi_pixel_format format; | 324 | enum mipi_dsi_pixel_format format; |
321 | unsigned long mode_flags; | 325 | unsigned long mode_flags; |
322 | const struct dsim_hblank_par *hpar; | 326 | const struct dsim_hblank_par *hpar; |
323 | unsigned int pms; | 327 | unsigned int pms; |
324 | unsigned int p; | 328 | unsigned int p; |
325 | unsigned int m; | 329 | unsigned int m; |
326 | unsigned int s; | 330 | unsigned int s; |
327 | unsigned long long lp_data_rate; | 331 | unsigned long long lp_data_rate; |
328 | unsigned long long hs_data_rate; | 332 | unsigned long long hs_data_rate; |
329 | struct videomode vmode; | 333 | struct videomode vmode; |
330 | 334 | ||
331 | struct completion pll_stable; | 335 | struct completion pll_stable; |
332 | struct completion ph_tx_done; | 336 | struct completion ph_tx_done; |
333 | struct completion pl_tx_done; | 337 | struct completion pl_tx_done; |
334 | struct completion rx_done; | 338 | struct completion rx_done; |
335 | const struct sec_mipi_dsim_plat_data *pdata; | 339 | const struct sec_mipi_dsim_plat_data *pdata; |
336 | }; | 340 | }; |
337 | 341 | ||
338 | #define DSIM_HBLANK_PARAM(nm, vf, hfp, hbp, hsa, num) \ | 342 | #define DSIM_HBLANK_PARAM(nm, vf, hfp, hbp, hsa, num) \ |
339 | .name = (nm), \ | 343 | .name = (nm), \ |
340 | .vrefresh = (vf), \ | 344 | .vrefresh = (vf), \ |
341 | .hfp_wc = (hfp), \ | 345 | .hfp_wc = (hfp), \ |
342 | .hbp_wc = (hbp), \ | 346 | .hbp_wc = (hbp), \ |
343 | .hsa_wc = (hsa), \ | 347 | .hsa_wc = (hsa), \ |
344 | .lanes = (num) | 348 | .lanes = (num) |
345 | 349 | ||
346 | #define DSIM_PLL_PMS(c, pp, mm, ss) \ | 350 | #define DSIM_PLL_PMS(c, pp, mm, ss) \ |
347 | .bit_clk = (c), \ | 351 | .bit_clk = (c), \ |
348 | .p = (pp), \ | 352 | .p = (pp), \ |
349 | .m = (mm), \ | 353 | .m = (mm), \ |
350 | .s = (ss) | 354 | .s = (ss) |
351 | 355 | ||
352 | static const struct dsim_hblank_par hblank_4lanes[] = { | 356 | static const struct dsim_hblank_par hblank_4lanes[] = { |
353 | /* { 88, 148, 44 } */ | 357 | /* { 88, 148, 44 } */ |
354 | { DSIM_HBLANK_PARAM("1920x1080", 60, 60, 105, 27, 4), }, | 358 | { DSIM_HBLANK_PARAM("1920x1080", 60, 60, 105, 27, 4), }, |
355 | /* { 528, 148, 44 } */ | 359 | /* { 528, 148, 44 } */ |
356 | { DSIM_HBLANK_PARAM("1920x1080", 50, 390, 105, 27, 4), }, | 360 | { DSIM_HBLANK_PARAM("1920x1080", 50, 390, 105, 27, 4), }, |
357 | /* { 88, 148, 44 } */ | 361 | /* { 88, 148, 44 } */ |
358 | { DSIM_HBLANK_PARAM("1920x1080", 30, 60, 105, 27, 4), }, | 362 | { DSIM_HBLANK_PARAM("1920x1080", 30, 60, 105, 27, 4), }, |
359 | /* { 110, 220, 40 } */ | 363 | /* { 110, 220, 40 } */ |
360 | { DSIM_HBLANK_PARAM("1280x720" , 60, 78, 159, 24, 4), }, | 364 | { DSIM_HBLANK_PARAM("1280x720" , 60, 78, 159, 24, 4), }, |
361 | /* { 440, 220, 40 } */ | 365 | /* { 440, 220, 40 } */ |
362 | { DSIM_HBLANK_PARAM("1280x720" , 50, 324, 159, 24, 4), }, | 366 | { DSIM_HBLANK_PARAM("1280x720" , 50, 324, 159, 24, 4), }, |
363 | /* { 16, 60, 62 } */ | 367 | /* { 16, 60, 62 } */ |
364 | { DSIM_HBLANK_PARAM("720x480" , 60, 6, 39, 40, 4), }, | 368 | { DSIM_HBLANK_PARAM("720x480" , 60, 6, 39, 40, 4), }, |
365 | /* { 12, 68, 64 } */ | 369 | /* { 12, 68, 64 } */ |
366 | { DSIM_HBLANK_PARAM("720x576" , 50, 3, 45, 42, 4), }, | 370 | { DSIM_HBLANK_PARAM("720x576" , 50, 3, 45, 42, 4), }, |
367 | /* { 16, 48, 96 } */ | 371 | /* { 16, 48, 96 } */ |
368 | { DSIM_HBLANK_PARAM("640x480" , 60, 6, 30, 66, 4), }, | 372 | { DSIM_HBLANK_PARAM("640x480" , 60, 6, 30, 66, 4), }, |
369 | }; | 373 | }; |
370 | 374 | ||
371 | static const struct dsim_hblank_par hblank_2lanes[] = { | 375 | static const struct dsim_hblank_par hblank_2lanes[] = { |
372 | /* { 88, 148, 44 } */ | 376 | /* { 88, 148, 44 } */ |
373 | { DSIM_HBLANK_PARAM("1920x1080", 30, 114, 210, 60, 2), }, | 377 | { DSIM_HBLANK_PARAM("1920x1080", 30, 114, 210, 60, 2), }, |
374 | /* { 110, 220, 40 } */ | 378 | /* { 110, 220, 40 } */ |
375 | { DSIM_HBLANK_PARAM("1280x720" , 60, 159, 320, 40, 2), }, | 379 | { DSIM_HBLANK_PARAM("1280x720" , 60, 159, 320, 40, 2), }, |
376 | /* { 440, 220, 40 } */ | 380 | /* { 440, 220, 40 } */ |
377 | { DSIM_HBLANK_PARAM("1280x720" , 50, 654, 320, 40, 2), }, | 381 | { DSIM_HBLANK_PARAM("1280x720" , 50, 654, 320, 40, 2), }, |
378 | /* { 16, 60, 62 } */ | 382 | /* { 16, 60, 62 } */ |
379 | { DSIM_HBLANK_PARAM("720x480" , 60, 16, 66, 88, 2), }, | 383 | { DSIM_HBLANK_PARAM("720x480" , 60, 16, 66, 88, 2), }, |
380 | /* { 12, 68, 64 } */ | 384 | /* { 12, 68, 64 } */ |
381 | { DSIM_HBLANK_PARAM("720x576" , 50, 12, 96, 72, 2), }, | 385 | { DSIM_HBLANK_PARAM("720x576" , 50, 12, 96, 72, 2), }, |
382 | /* { 16, 48, 96 } */ | 386 | /* { 16, 48, 96 } */ |
383 | { DSIM_HBLANK_PARAM("640x480" , 60, 18, 66, 138, 2), }, | 387 | { DSIM_HBLANK_PARAM("640x480" , 60, 18, 66, 138, 2), }, |
384 | }; | 388 | }; |
385 | 389 | ||
386 | static const struct dsim_pll_pms pll_pms[] = { | 390 | static const struct dsim_pll_pms pll_pms[] = { |
387 | { DSIM_PLL_PMS(891000, 1, 66, 1), }, | 391 | { DSIM_PLL_PMS(891000, 1, 66, 1), }, |
388 | { DSIM_PLL_PMS(890112, 1, 66, 1), }, | 392 | { DSIM_PLL_PMS(890112, 1, 66, 1), }, |
389 | { DSIM_PLL_PMS(594000, 3, 66, 0), }, | 393 | { DSIM_PLL_PMS(594000, 3, 66, 0), }, |
390 | { DSIM_PLL_PMS(593408, 3, 66, 0), }, | 394 | { DSIM_PLL_PMS(593408, 3, 66, 0), }, |
391 | { DSIM_PLL_PMS(445500, 1, 66, 2), }, | 395 | { DSIM_PLL_PMS(445500, 1, 66, 2), }, |
392 | { DSIM_PLL_PMS(445056, 1, 66, 2), }, | 396 | { DSIM_PLL_PMS(445056, 1, 66, 2), }, |
393 | { DSIM_PLL_PMS(324000, 3, 72, 1), }, | 397 | { DSIM_PLL_PMS(324000, 3, 72, 1), }, |
394 | { DSIM_PLL_PMS(324324, 3, 72, 1), }, | 398 | { DSIM_PLL_PMS(324324, 3, 72, 1), }, |
395 | { DSIM_PLL_PMS(162000, 3, 72, 2), }, | 399 | { DSIM_PLL_PMS(162000, 3, 72, 2), }, |
396 | { DSIM_PLL_PMS(162162, 3, 72, 2), }, | 400 | { DSIM_PLL_PMS(162162, 3, 72, 2), }, |
397 | }; | 401 | }; |
398 | 402 | ||
399 | static const struct dsim_hblank_par *sec_mipi_dsim_get_hblank_par(const char *name, | 403 | static const struct dsim_hblank_par *sec_mipi_dsim_get_hblank_par(const char *name, |
400 | int vrefresh, | 404 | int vrefresh, |
401 | int lanes) | 405 | int lanes) |
402 | { | 406 | { |
403 | int i, size; | 407 | int i, size; |
404 | const struct dsim_hblank_par *hpar, *hblank; | 408 | const struct dsim_hblank_par *hpar, *hblank; |
405 | 409 | ||
406 | if (unlikely(!name)) | 410 | if (unlikely(!name)) |
407 | return NULL; | 411 | return NULL; |
408 | 412 | ||
409 | switch (lanes) { | 413 | switch (lanes) { |
410 | case 2: | 414 | case 2: |
411 | hblank = hblank_2lanes; | 415 | hblank = hblank_2lanes; |
412 | size = ARRAY_SIZE(hblank_2lanes); | 416 | size = ARRAY_SIZE(hblank_2lanes); |
413 | break; | 417 | break; |
414 | case 4: | 418 | case 4: |
415 | hblank = hblank_4lanes; | 419 | hblank = hblank_4lanes; |
416 | size = ARRAY_SIZE(hblank_4lanes); | 420 | size = ARRAY_SIZE(hblank_4lanes); |
417 | break; | 421 | break; |
418 | default: | 422 | default: |
419 | pr_err("No hblank data for mode %s with %d lanes\n", | 423 | pr_err("No hblank data for mode %s with %d lanes\n", |
420 | name, lanes); | 424 | name, lanes); |
421 | return NULL; | 425 | return NULL; |
422 | } | 426 | } |
423 | 427 | ||
424 | for (i = 0; i < size; i++) { | 428 | for (i = 0; i < size; i++) { |
425 | hpar = &hblank[i]; | 429 | hpar = &hblank[i]; |
426 | 430 | ||
427 | if (!strcmp(name, hpar->name)) { | 431 | if (!strcmp(name, hpar->name)) { |
428 | if (vrefresh != hpar->vrefresh) | 432 | if (vrefresh != hpar->vrefresh) |
429 | continue; | 433 | continue; |
430 | 434 | ||
431 | /* found */ | 435 | /* found */ |
432 | return hpar; | 436 | return hpar; |
433 | } | 437 | } |
434 | } | 438 | } |
435 | 439 | ||
436 | return NULL; | 440 | return NULL; |
437 | } | 441 | } |
438 | 442 | ||
439 | static const struct dsim_pll_pms *sec_mipi_dsim_get_pms(uint32_t bit_clk) | 443 | static const struct dsim_pll_pms *sec_mipi_dsim_get_pms(uint32_t bit_clk) |
440 | { | 444 | { |
441 | int i; | 445 | int i; |
442 | const struct dsim_pll_pms *pms; | 446 | const struct dsim_pll_pms *pms; |
443 | 447 | ||
444 | for (i = 0; i < ARRAY_SIZE(pll_pms); i++) { | 448 | for (i = 0; i < ARRAY_SIZE(pll_pms); i++) { |
445 | pms = &pll_pms[i]; | 449 | pms = &pll_pms[i]; |
446 | 450 | ||
447 | if (bit_clk == pms->bit_clk) | 451 | if (bit_clk == pms->bit_clk) |
448 | return pms; | 452 | return pms; |
449 | } | 453 | } |
450 | 454 | ||
451 | return NULL; | 455 | return NULL; |
452 | } | 456 | } |
453 | 457 | ||
454 | static void sec_mipi_dsim_irq_init(struct sec_mipi_dsim *dsim); | 458 | static void sec_mipi_dsim_irq_init(struct sec_mipi_dsim *dsim); |
455 | 459 | ||
456 | /* For now, dsim only support one device attached */ | 460 | /* For now, dsim only support one device attached */ |
457 | static int sec_mipi_dsim_host_attach(struct mipi_dsi_host *host, | 461 | static int sec_mipi_dsim_host_attach(struct mipi_dsi_host *host, |
458 | struct mipi_dsi_device *dsi) | 462 | struct mipi_dsi_device *dsi) |
459 | { | 463 | { |
460 | struct sec_mipi_dsim *dsim = to_sec_mipi_dsim(host); | 464 | struct sec_mipi_dsim *dsim = to_sec_mipi_dsim(host); |
461 | const struct sec_mipi_dsim_plat_data *pdata = dsim->pdata; | 465 | const struct sec_mipi_dsim_plat_data *pdata = dsim->pdata; |
462 | struct device *dev = dsim->dev; | 466 | struct device *dev = dsim->dev; |
463 | struct drm_panel *panel; | 467 | struct drm_panel *panel; |
464 | 468 | ||
465 | if (!dsi->lanes || dsi->lanes > pdata->max_data_lanes) { | 469 | if (!dsi->lanes || dsi->lanes > pdata->max_data_lanes) { |
466 | dev_err(dev, "invalid data lanes number\n"); | 470 | dev_err(dev, "invalid data lanes number\n"); |
467 | return -EINVAL; | 471 | return -EINVAL; |
468 | } | 472 | } |
469 | 473 | ||
470 | if (dsim->channel) | 474 | if (dsim->channel) |
471 | return -EINVAL; | 475 | return -EINVAL; |
472 | 476 | ||
473 | if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO) || | 477 | if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO) || |
474 | !((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) || | 478 | !((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) || |
475 | (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE))) { | 479 | (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE))) { |
476 | dev_err(dev, "unsupported dsi mode\n"); | 480 | dev_err(dev, "unsupported dsi mode\n"); |
477 | return -EINVAL; | 481 | return -EINVAL; |
478 | } | 482 | } |
479 | 483 | ||
480 | if (dsi->format != MIPI_DSI_FMT_RGB888 && | 484 | if (dsi->format != MIPI_DSI_FMT_RGB888 && |
481 | dsi->format != MIPI_DSI_FMT_RGB565 && | 485 | dsi->format != MIPI_DSI_FMT_RGB565 && |
482 | dsi->format != MIPI_DSI_FMT_RGB666 && | 486 | dsi->format != MIPI_DSI_FMT_RGB666 && |
483 | dsi->format != MIPI_DSI_FMT_RGB666_PACKED) { | 487 | dsi->format != MIPI_DSI_FMT_RGB666_PACKED) { |
484 | dev_err(dev, "unsupported pixel format: %#x\n", dsi->format); | 488 | dev_err(dev, "unsupported pixel format: %#x\n", dsi->format); |
485 | return -EINVAL; | 489 | return -EINVAL; |
486 | } | 490 | } |
487 | 491 | ||
488 | if (!dsim->next) { | 492 | if (!dsim->next) { |
489 | /* 'dsi' must be panel device */ | 493 | /* 'dsi' must be panel device */ |
490 | panel = of_drm_find_panel(dsi->dev.of_node); | 494 | panel = of_drm_find_panel(dsi->dev.of_node); |
491 | 495 | ||
492 | if (!panel) { | 496 | if (!panel) { |
493 | dev_err(dev, "refuse unknown dsi device attach\n"); | 497 | dev_err(dev, "refuse unknown dsi device attach\n"); |
494 | WARN_ON(!panel); | 498 | WARN_ON(!panel); |
495 | return -ENODEV; | 499 | return -ENODEV; |
496 | } | 500 | } |
497 | 501 | ||
498 | /* Don't support multiple panels */ | 502 | /* Don't support multiple panels */ |
499 | if (dsim->panel && panel && dsim->panel != panel) { | 503 | if (dsim->panel && panel && dsim->panel != panel) { |
500 | dev_err(dev, "don't support multiple panels\n"); | 504 | dev_err(dev, "don't support multiple panels\n"); |
501 | return -EBUSY; | 505 | return -EBUSY; |
502 | } | 506 | } |
503 | 507 | ||
504 | dsim->panel = panel; | 508 | dsim->panel = panel; |
505 | } | 509 | } |
506 | 510 | ||
507 | /* TODO: DSIM 3 lanes has some display issue, so | 511 | /* TODO: DSIM 3 lanes has some display issue, so |
508 | * avoid 3 lanes enable, and force data lanes to | 512 | * avoid 3 lanes enable, and force data lanes to |
509 | * be 2. | 513 | * be 2. |
510 | */ | 514 | */ |
511 | if (dsi->lanes == 3) | 515 | if (dsi->lanes == 3) |
512 | dsi->lanes = 2; | 516 | dsi->lanes = 2; |
513 | 517 | ||
514 | dsim->lanes = dsi->lanes; | 518 | dsim->lanes = dsi->lanes; |
515 | dsim->channel = dsi->channel; | 519 | dsim->channel = dsi->channel; |
516 | dsim->format = dsi->format; | 520 | dsim->format = dsi->format; |
517 | dsim->mode_flags = dsi->mode_flags; | 521 | dsim->mode_flags = dsi->mode_flags; |
518 | 522 | ||
519 | /* TODO: support later */ | 523 | /* TODO: support later */ |
520 | #if 0 | 524 | #if 0 |
521 | if (dsim->connector.dev) | 525 | if (dsim->connector.dev) |
522 | drm_helper_hpd_irq_event(dsim->connector.dev); | 526 | drm_helper_hpd_irq_event(dsim->connector.dev); |
523 | #endif | 527 | #endif |
524 | 528 | ||
525 | return 0; | 529 | return 0; |
526 | } | 530 | } |
527 | 531 | ||
528 | static int sec_mipi_dsim_host_detach(struct mipi_dsi_host *host, | 532 | static int sec_mipi_dsim_host_detach(struct mipi_dsi_host *host, |
529 | struct mipi_dsi_device *dsi) | 533 | struct mipi_dsi_device *dsi) |
530 | { | 534 | { |
531 | struct sec_mipi_dsim *dsim = to_sec_mipi_dsim(host); | 535 | struct sec_mipi_dsim *dsim = to_sec_mipi_dsim(host); |
532 | 536 | ||
533 | if (WARN_ON(!dsim->next && !dsim->panel)) | 537 | if (WARN_ON(!dsim->next && !dsim->panel)) |
534 | return -ENODEV; | 538 | return -ENODEV; |
535 | 539 | ||
536 | /* clear the saved dsi parameters */ | 540 | /* clear the saved dsi parameters */ |
537 | dsim->lanes = 0; | 541 | dsim->lanes = 0; |
538 | dsim->channel = 0; | 542 | dsim->channel = 0; |
539 | dsim->format = 0; | 543 | dsim->format = 0; |
540 | dsim->mode_flags = 0; | 544 | dsim->mode_flags = 0; |
541 | 545 | ||
542 | return 0; | 546 | return 0; |
543 | } | 547 | } |
544 | 548 | ||
545 | static void sec_mipi_dsim_config_cmd_lpm(struct sec_mipi_dsim *dsim, | 549 | static void sec_mipi_dsim_config_cmd_lpm(struct sec_mipi_dsim *dsim, |
546 | bool enable) | 550 | bool enable) |
547 | { | 551 | { |
548 | uint32_t escmode; | 552 | uint32_t escmode; |
549 | 553 | ||
550 | escmode = dsim_read(dsim, DSIM_ESCMODE); | 554 | escmode = dsim_read(dsim, DSIM_ESCMODE); |
551 | 555 | ||
552 | if (enable) | 556 | if (enable) |
553 | escmode |= ESCMODE_CMDLPDT; | 557 | escmode |= ESCMODE_CMDLPDT; |
554 | else | 558 | else |
555 | escmode &= ~ESCMODE_CMDLPDT; | 559 | escmode &= ~ESCMODE_CMDLPDT; |
556 | 560 | ||
557 | dsim_write(dsim, escmode, DSIM_ESCMODE); | 561 | dsim_write(dsim, escmode, DSIM_ESCMODE); |
558 | } | 562 | } |
559 | 563 | ||
560 | static void sec_mipi_dsim_write_pl_to_sfr_fifo(struct sec_mipi_dsim *dsim, | 564 | static void sec_mipi_dsim_write_pl_to_sfr_fifo(struct sec_mipi_dsim *dsim, |
561 | const void *payload, | 565 | const void *payload, |
562 | size_t length) | 566 | size_t length) |
563 | { | 567 | { |
564 | uint32_t pl_data; | 568 | uint32_t pl_data; |
565 | 569 | ||
566 | if (!length) | 570 | if (!length) |
567 | return; | 571 | return; |
568 | 572 | ||
569 | while (length >= 4) { | 573 | while (length >= 4) { |
570 | pl_data = get_unaligned_le32(payload); | 574 | pl_data = get_unaligned_le32(payload); |
571 | dsim_write(dsim, pl_data, DSIM_PAYLOAD); | 575 | dsim_write(dsim, pl_data, DSIM_PAYLOAD); |
572 | payload += 4; | 576 | payload += 4; |
573 | length -= 4; | 577 | length -= 4; |
574 | } | 578 | } |
575 | 579 | ||
576 | pl_data = 0; | 580 | pl_data = 0; |
577 | switch (length) { | 581 | switch (length) { |
578 | case 3: | 582 | case 3: |
579 | pl_data |= ((u8 *)payload)[2] << 16; | 583 | pl_data |= ((u8 *)payload)[2] << 16; |
580 | case 2: | 584 | case 2: |
581 | pl_data |= ((u8 *)payload)[1] << 8; | 585 | pl_data |= ((u8 *)payload)[1] << 8; |
582 | case 1: | 586 | case 1: |
583 | pl_data |= ((u8 *)payload)[0]; | 587 | pl_data |= ((u8 *)payload)[0]; |
584 | dsim_write(dsim, pl_data, DSIM_PAYLOAD); | 588 | dsim_write(dsim, pl_data, DSIM_PAYLOAD); |
585 | break; | 589 | break; |
586 | } | 590 | } |
587 | } | 591 | } |
588 | 592 | ||
589 | static void sec_mipi_dsim_write_ph_to_sfr_fifo(struct sec_mipi_dsim *dsim, | 593 | static void sec_mipi_dsim_write_ph_to_sfr_fifo(struct sec_mipi_dsim *dsim, |
590 | void *header, | 594 | void *header, |
591 | bool use_lpm) | 595 | bool use_lpm) |
592 | { | 596 | { |
593 | uint32_t pkthdr; | 597 | uint32_t pkthdr; |
594 | 598 | ||
595 | pkthdr = PKTHDR_SET_DATA1(((u8 *)header)[2]) | /* WC MSB */ | 599 | pkthdr = PKTHDR_SET_DATA1(((u8 *)header)[2]) | /* WC MSB */ |
596 | PKTHDR_SET_DATA0(((u8 *)header)[1]) | /* WC LSB */ | 600 | PKTHDR_SET_DATA0(((u8 *)header)[1]) | /* WC LSB */ |
597 | PKTHDR_SET_DI(((u8 *)header)[0]); /* Data ID */ | 601 | PKTHDR_SET_DI(((u8 *)header)[0]); /* Data ID */ |
598 | 602 | ||
599 | dsim_write(dsim, pkthdr, DSIM_PKTHDR); | 603 | dsim_write(dsim, pkthdr, DSIM_PKTHDR); |
600 | } | 604 | } |
601 | 605 | ||
602 | static int sec_mipi_dsim_read_pl_from_sfr_fifo(struct sec_mipi_dsim *dsim, | 606 | static int sec_mipi_dsim_read_pl_from_sfr_fifo(struct sec_mipi_dsim *dsim, |
603 | void *payload, | 607 | void *payload, |
604 | size_t length) | 608 | size_t length) |
605 | { | 609 | { |
606 | uint8_t data_type; | 610 | uint8_t data_type; |
607 | uint16_t word_count = 0; | 611 | uint16_t word_count = 0; |
608 | uint32_t fifoctrl, ph, pl; | 612 | uint32_t fifoctrl, ph, pl; |
609 | 613 | ||
610 | fifoctrl = dsim_read(dsim, DSIM_FIFOCTRL); | 614 | fifoctrl = dsim_read(dsim, DSIM_FIFOCTRL); |
611 | 615 | ||
612 | if (WARN_ON(fifoctrl & FIFOCTRL_EMPTYRX)) | 616 | if (WARN_ON(fifoctrl & FIFOCTRL_EMPTYRX)) |
613 | return -EINVAL; | 617 | return -EINVAL; |
614 | 618 | ||
615 | ph = dsim_read(dsim, DSIM_RXFIFO); | 619 | ph = dsim_read(dsim, DSIM_RXFIFO); |
616 | data_type = PKTHDR_GET_DT(ph); | 620 | data_type = PKTHDR_GET_DT(ph); |
617 | switch (data_type) { | 621 | switch (data_type) { |
618 | case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT: | 622 | case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT: |
619 | dev_err(dsim->dev, "peripheral report error: (0-7)%x, (8-15)%x\n", | 623 | dev_err(dsim->dev, "peripheral report error: (0-7)%x, (8-15)%x\n", |
620 | PKTHDR_GET_DATA0(ph), PKTHDR_GET_DATA1(ph)); | 624 | PKTHDR_GET_DATA0(ph), PKTHDR_GET_DATA1(ph)); |
621 | return -EPROTO; | 625 | return -EPROTO; |
622 | case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE: | 626 | case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE: |
623 | case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE: | 627 | case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE: |
624 | if (!WARN_ON(length < 2)) { | 628 | if (!WARN_ON(length < 2)) { |
625 | ((u8 *)payload)[1] = PKTHDR_GET_DATA1(ph); | 629 | ((u8 *)payload)[1] = PKTHDR_GET_DATA1(ph); |
626 | word_count++; | 630 | word_count++; |
627 | } | 631 | } |
628 | /* fall through */ | 632 | /* fall through */ |
629 | case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE: | 633 | case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE: |
630 | case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE: | 634 | case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE: |
631 | ((u8 *)payload)[0] = PKTHDR_GET_DATA0(ph); | 635 | ((u8 *)payload)[0] = PKTHDR_GET_DATA0(ph); |
632 | word_count++; | 636 | word_count++; |
633 | length = word_count; | 637 | length = word_count; |
634 | break; | 638 | break; |
635 | case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE: | 639 | case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE: |
636 | case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE: | 640 | case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE: |
637 | word_count = PKTHDR_GET_WC(ph); | 641 | word_count = PKTHDR_GET_WC(ph); |
638 | if (word_count > length) { | 642 | if (word_count > length) { |
639 | dev_err(dsim->dev, "invalid receive buffer length\n"); | 643 | dev_err(dsim->dev, "invalid receive buffer length\n"); |
640 | return -EINVAL; | 644 | return -EINVAL; |
641 | } | 645 | } |
642 | 646 | ||
643 | length = word_count; | 647 | length = word_count; |
644 | 648 | ||
645 | while (word_count >= 4) { | 649 | while (word_count >= 4) { |
646 | pl = dsim_read(dsim, DSIM_RXFIFO); | 650 | pl = dsim_read(dsim, DSIM_RXFIFO); |
647 | ((u8 *)payload)[0] = pl & 0xff; | 651 | ((u8 *)payload)[0] = pl & 0xff; |
648 | ((u8 *)payload)[1] = (pl >> 8) & 0xff; | 652 | ((u8 *)payload)[1] = (pl >> 8) & 0xff; |
649 | ((u8 *)payload)[2] = (pl >> 16) & 0xff; | 653 | ((u8 *)payload)[2] = (pl >> 16) & 0xff; |
650 | ((u8 *)payload)[3] = (pl >> 24) & 0xff; | 654 | ((u8 *)payload)[3] = (pl >> 24) & 0xff; |
651 | payload += 4; | 655 | payload += 4; |
652 | word_count -= 4; | 656 | word_count -= 4; |
653 | } | 657 | } |
654 | 658 | ||
655 | if (word_count > 0) { | 659 | if (word_count > 0) { |
656 | pl = dsim_read(dsim, DSIM_RXFIFO); | 660 | pl = dsim_read(dsim, DSIM_RXFIFO); |
657 | 661 | ||
658 | switch (word_count) { | 662 | switch (word_count) { |
659 | case 3: | 663 | case 3: |
660 | ((u8 *)payload)[2] = (pl >> 16) & 0xff; | 664 | ((u8 *)payload)[2] = (pl >> 16) & 0xff; |
661 | case 2: | 665 | case 2: |
662 | ((u8 *)payload)[1] = (pl >> 8) & 0xff; | 666 | ((u8 *)payload)[1] = (pl >> 8) & 0xff; |
663 | case 1: | 667 | case 1: |
664 | ((u8 *)payload)[0] = pl & 0xff; | 668 | ((u8 *)payload)[0] = pl & 0xff; |
665 | break; | 669 | break; |
666 | } | 670 | } |
667 | } | 671 | } |
668 | 672 | ||
669 | break; | 673 | break; |
670 | default: | 674 | default: |
671 | return -EINVAL; | 675 | return -EINVAL; |
672 | } | 676 | } |
673 | 677 | ||
674 | return length; | 678 | return length; |
675 | } | 679 | } |
676 | 680 | ||
677 | static ssize_t sec_mipi_dsim_host_transfer(struct mipi_dsi_host *host, | 681 | static ssize_t sec_mipi_dsim_host_transfer(struct mipi_dsi_host *host, |
678 | const struct mipi_dsi_msg *msg) | 682 | const struct mipi_dsi_msg *msg) |
679 | { | 683 | { |
680 | int ret; | 684 | int ret; |
681 | bool use_lpm; | 685 | bool use_lpm; |
682 | struct mipi_dsi_packet packet; | 686 | struct mipi_dsi_packet packet; |
683 | struct sec_mipi_dsim *dsim = to_sec_mipi_dsim(host); | 687 | struct sec_mipi_dsim *dsim = to_sec_mipi_dsim(host); |
684 | 688 | ||
685 | if ((msg->rx_buf && !msg->rx_len) || (msg->rx_len && !msg->rx_buf)) | 689 | if ((msg->rx_buf && !msg->rx_len) || (msg->rx_len && !msg->rx_buf)) |
686 | return -EINVAL; | 690 | return -EINVAL; |
687 | 691 | ||
688 | ret = mipi_dsi_create_packet(&packet, msg); | 692 | ret = mipi_dsi_create_packet(&packet, msg); |
689 | if (ret) { | 693 | if (ret) { |
690 | dev_err(dsim->dev, "failed to create dsi packet: %d\n", ret); | 694 | dev_err(dsim->dev, "failed to create dsi packet: %d\n", ret); |
691 | return ret; | 695 | return ret; |
692 | } | 696 | } |
693 | 697 | ||
694 | /* need to read data from peripheral */ | 698 | /* need to read data from peripheral */ |
695 | if (unlikely(msg->rx_buf)) | 699 | if (unlikely(msg->rx_buf)) |
696 | reinit_completion(&dsim->rx_done); | 700 | reinit_completion(&dsim->rx_done); |
697 | 701 | ||
698 | /* config LPM for CMD TX */ | 702 | /* config LPM for CMD TX */ |
699 | use_lpm = msg->flags & MIPI_DSI_MSG_USE_LPM ? true : false; | 703 | use_lpm = msg->flags & MIPI_DSI_MSG_USE_LPM ? true : false; |
700 | sec_mipi_dsim_config_cmd_lpm(dsim, use_lpm); | 704 | sec_mipi_dsim_config_cmd_lpm(dsim, use_lpm); |
701 | 705 | ||
702 | if (packet.payload_length) { /* Long Packet case */ | 706 | if (packet.payload_length) { /* Long Packet case */ |
703 | reinit_completion(&dsim->pl_tx_done); | 707 | reinit_completion(&dsim->pl_tx_done); |
704 | 708 | ||
705 | /* write packet payload */ | 709 | /* write packet payload */ |
706 | sec_mipi_dsim_write_pl_to_sfr_fifo(dsim, | 710 | sec_mipi_dsim_write_pl_to_sfr_fifo(dsim, |
707 | packet.payload, | 711 | packet.payload, |
708 | packet.payload_length); | 712 | packet.payload_length); |
709 | 713 | ||
710 | /* write packet header */ | 714 | /* write packet header */ |
711 | sec_mipi_dsim_write_ph_to_sfr_fifo(dsim, | 715 | sec_mipi_dsim_write_ph_to_sfr_fifo(dsim, |
712 | packet.header, | 716 | packet.header, |
713 | use_lpm); | 717 | use_lpm); |
714 | 718 | ||
715 | ret = wait_for_completion_timeout(&dsim->ph_tx_done, | 719 | ret = wait_for_completion_timeout(&dsim->ph_tx_done, |
716 | MIPI_FIFO_TIMEOUT); | 720 | MIPI_FIFO_TIMEOUT); |
717 | if (!ret) { | 721 | if (!ret) { |
718 | dev_err(dsim->dev, "wait payload tx done time out\n"); | 722 | dev_err(dsim->dev, "wait payload tx done time out\n"); |
719 | return -EBUSY; | 723 | return -EBUSY; |
720 | } | 724 | } |
721 | } else { | 725 | } else { |
722 | reinit_completion(&dsim->ph_tx_done); | 726 | reinit_completion(&dsim->ph_tx_done); |
723 | 727 | ||
724 | /* write packet header */ | 728 | /* write packet header */ |
725 | sec_mipi_dsim_write_ph_to_sfr_fifo(dsim, | 729 | sec_mipi_dsim_write_ph_to_sfr_fifo(dsim, |
726 | packet.header, | 730 | packet.header, |
727 | use_lpm); | 731 | use_lpm); |
728 | 732 | ||
729 | ret = wait_for_completion_timeout(&dsim->ph_tx_done, | 733 | ret = wait_for_completion_timeout(&dsim->ph_tx_done, |
730 | MIPI_FIFO_TIMEOUT); | 734 | MIPI_FIFO_TIMEOUT); |
731 | if (!ret) { | 735 | if (!ret) { |
732 | dev_err(dsim->dev, "wait pkthdr tx done time out\n"); | 736 | dev_err(dsim->dev, "wait pkthdr tx done time out\n"); |
733 | return -EBUSY; | 737 | return -EBUSY; |
734 | } | 738 | } |
735 | } | 739 | } |
736 | 740 | ||
737 | /* read packet payload */ | 741 | /* read packet payload */ |
738 | if (unlikely(msg->rx_buf)) { | 742 | if (unlikely(msg->rx_buf)) { |
739 | ret = wait_for_completion_timeout(&dsim->rx_done, | 743 | ret = wait_for_completion_timeout(&dsim->rx_done, |
740 | MIPI_FIFO_TIMEOUT); | 744 | MIPI_FIFO_TIMEOUT); |
741 | if (!ret) { | 745 | if (!ret) { |
742 | dev_err(dsim->dev, "wait rx done time out\n"); | 746 | dev_err(dsim->dev, "wait rx done time out\n"); |
743 | return -EBUSY; | 747 | return -EBUSY; |
744 | } | 748 | } |
745 | 749 | ||
746 | ret = sec_mipi_dsim_read_pl_from_sfr_fifo(dsim, | 750 | ret = sec_mipi_dsim_read_pl_from_sfr_fifo(dsim, |
747 | msg->rx_buf, | 751 | msg->rx_buf, |
748 | msg->rx_len); | 752 | msg->rx_len); |
749 | if (ret < 0) | 753 | if (ret < 0) |
750 | return ret; | 754 | return ret; |
751 | } | 755 | } |
752 | 756 | ||
753 | return 0; | 757 | return 0; |
754 | } | 758 | } |
755 | 759 | ||
756 | static const struct mipi_dsi_host_ops sec_mipi_dsim_host_ops = { | 760 | static const struct mipi_dsi_host_ops sec_mipi_dsim_host_ops = { |
757 | .attach = sec_mipi_dsim_host_attach, | 761 | .attach = sec_mipi_dsim_host_attach, |
758 | .detach = sec_mipi_dsim_host_detach, | 762 | .detach = sec_mipi_dsim_host_detach, |
759 | .transfer = sec_mipi_dsim_host_transfer, | 763 | .transfer = sec_mipi_dsim_host_transfer, |
760 | }; | 764 | }; |
761 | 765 | ||
762 | static int sec_mipi_dsim_bridge_attach(struct drm_bridge *bridge) | 766 | static int sec_mipi_dsim_bridge_attach(struct drm_bridge *bridge) |
763 | { | 767 | { |
764 | int ret; | 768 | int ret; |
765 | struct sec_mipi_dsim *dsim = bridge->driver_private; | 769 | struct sec_mipi_dsim *dsim = bridge->driver_private; |
766 | struct device *dev = dsim->dev; | 770 | struct device *dev = dsim->dev; |
767 | struct device_node *np = dev->of_node; | 771 | struct device_node *np = dev->of_node; |
768 | struct device_node *endpoint, *remote; | 772 | struct device_node *endpoint, *remote; |
769 | struct drm_bridge *next = NULL; | 773 | struct drm_bridge *next = NULL; |
770 | struct drm_encoder *encoder = dsim->encoder; | 774 | struct drm_encoder *encoder = dsim->encoder; |
771 | 775 | ||
772 | /* TODO: All bridges and planes should have already been added */ | 776 | /* TODO: All bridges and planes should have already been added */ |
773 | 777 | ||
774 | /* A panel has been found, ignor other dsi devices */ | 778 | /* A panel has been found, ignor other dsi devices */ |
775 | if (dsim->panel) | 779 | if (dsim->panel) |
776 | return 0; | 780 | return 0; |
777 | 781 | ||
778 | /* find next bridge */ | 782 | /* find next bridge */ |
779 | endpoint = of_graph_get_next_endpoint(np, NULL); | 783 | endpoint = of_graph_get_next_endpoint(np, NULL); |
780 | /* At least one endpoint should be existed */ | 784 | /* At least one endpoint should be existed */ |
781 | if (!endpoint) | 785 | if (!endpoint) |
782 | return -ENODEV; | 786 | return -ENODEV; |
783 | 787 | ||
784 | while(endpoint && !next) { | 788 | while(endpoint && !next) { |
785 | remote = of_graph_get_remote_port_parent(endpoint); | 789 | remote = of_graph_get_remote_port_parent(endpoint); |
786 | 790 | ||
787 | if (!remote || !of_device_is_available(remote)) { | 791 | if (!remote || !of_device_is_available(remote)) { |
788 | of_node_put(remote); | 792 | of_node_put(remote); |
789 | endpoint = of_graph_get_next_endpoint(np, endpoint); | 793 | endpoint = of_graph_get_next_endpoint(np, endpoint); |
790 | continue; | 794 | continue; |
791 | } | 795 | } |
792 | 796 | ||
793 | next = of_drm_find_bridge(remote); | 797 | next = of_drm_find_bridge(remote); |
794 | if (next) { | 798 | if (next) { |
795 | /* Found */ | 799 | /* Found */ |
796 | of_node_put(endpoint); | 800 | of_node_put(endpoint); |
797 | break; | 801 | break; |
798 | } | 802 | } |
799 | 803 | ||
800 | endpoint = of_graph_get_next_endpoint(np, endpoint); | 804 | endpoint = of_graph_get_next_endpoint(np, endpoint); |
801 | } | 805 | } |
802 | 806 | ||
803 | /* No valid dsi device attached */ | 807 | /* No valid dsi device attached */ |
804 | if (!next) | 808 | if (!next) |
805 | return -ENODEV; | 809 | return -ENODEV; |
806 | 810 | ||
807 | /* duplicate bridges or next bridge exists */ | 811 | /* duplicate bridges or next bridge exists */ |
808 | WARN_ON(bridge == next || bridge->next || dsim->next); | 812 | WARN_ON(bridge == next || bridge->next || dsim->next); |
809 | 813 | ||
810 | dsim->next = next; | 814 | dsim->next = next; |
811 | next->encoder = encoder; | 815 | next->encoder = encoder; |
812 | ret = drm_bridge_attach(encoder, next, bridge); | 816 | ret = drm_bridge_attach(encoder, next, bridge); |
813 | if (ret) { | 817 | if (ret) { |
814 | dev_err(dev, "Unable to attach bridge %s: %d\n", | 818 | dev_err(dev, "Unable to attach bridge %s: %d\n", |
815 | remote->name, ret); | 819 | remote->name, ret); |
816 | dsim->next = NULL; | 820 | dsim->next = NULL; |
817 | return ret; | 821 | return ret; |
818 | } | 822 | } |
819 | 823 | ||
820 | /* bridge chains */ | 824 | /* bridge chains */ |
821 | bridge->next = next; | 825 | bridge->next = next; |
822 | 826 | ||
823 | return 0; | 827 | return 0; |
824 | } | 828 | } |
825 | 829 | ||
826 | static int sec_mipi_dsim_config_pll(struct sec_mipi_dsim *dsim) | 830 | static int sec_mipi_dsim_config_pll(struct sec_mipi_dsim *dsim) |
827 | { | 831 | { |
828 | int ret; | 832 | int ret; |
829 | uint32_t pllctrl = 0, status, data_lanes_en, stop; | 833 | uint32_t pllctrl = 0, status, data_lanes_en, stop; |
830 | 834 | ||
831 | dsim_write(dsim, 0x8000, DSIM_PLLTMR); | 835 | dsim_write(dsim, 0x8000, DSIM_PLLTMR); |
832 | 836 | ||
833 | /* TODO: config dp/dn swap if requires */ | 837 | /* TODO: config dp/dn swap if requires */ |
834 | 838 | ||
835 | pllctrl |= PLLCTRL_SET_PMS(dsim->pms) | PLLCTRL_PLLEN; | 839 | pllctrl |= PLLCTRL_SET_PMS(dsim->pms) | PLLCTRL_PLLEN; |
836 | dsim_write(dsim, pllctrl, DSIM_PLLCTRL); | 840 | dsim_write(dsim, pllctrl, DSIM_PLLCTRL); |
837 | 841 | ||
838 | ret = wait_for_completion_timeout(&dsim->pll_stable, HZ / 10); | 842 | ret = wait_for_completion_timeout(&dsim->pll_stable, HZ / 10); |
839 | if (!ret) { | 843 | if (!ret) { |
840 | dev_err(dsim->dev, "wait for pll stable time out\n"); | 844 | dev_err(dsim->dev, "wait for pll stable time out\n"); |
841 | return -EBUSY; | 845 | return -EBUSY; |
842 | } | 846 | } |
843 | 847 | ||
844 | /* wait for clk & data lanes to go to stop state */ | 848 | /* wait for clk & data lanes to go to stop state */ |
845 | mdelay(1); | 849 | mdelay(1); |
846 | 850 | ||
847 | data_lanes_en = (0x1 << dsim->lanes) - 1; | 851 | data_lanes_en = (0x1 << dsim->lanes) - 1; |
848 | status = dsim_read(dsim, DSIM_STATUS); | 852 | status = dsim_read(dsim, DSIM_STATUS); |
849 | if (!(status & STATUS_STOPSTATECLK)) { | 853 | if (!(status & STATUS_STOPSTATECLK)) { |
850 | dev_err(dsim->dev, "clock is not in stop state\n"); | 854 | dev_err(dsim->dev, "clock is not in stop state\n"); |
851 | return -EBUSY; | 855 | return -EBUSY; |
852 | } | 856 | } |
853 | 857 | ||
854 | stop = STATUS_GET_STOPSTATEDAT(status); | 858 | stop = STATUS_GET_STOPSTATEDAT(status); |
855 | if ((stop & data_lanes_en) != data_lanes_en) { | 859 | if ((stop & data_lanes_en) != data_lanes_en) { |
856 | dev_err(dsim->dev, | 860 | dev_err(dsim->dev, |
857 | "one or more data lanes is not in stop state\n"); | 861 | "one or more data lanes is not in stop state\n"); |
858 | return -EBUSY; | 862 | return -EBUSY; |
859 | } | 863 | } |
860 | 864 | ||
861 | return 0; | 865 | return 0; |
862 | } | 866 | } |
863 | 867 | ||
864 | static void sec_mipi_dsim_set_main_mode(struct sec_mipi_dsim *dsim) | 868 | static void sec_mipi_dsim_set_main_mode(struct sec_mipi_dsim *dsim) |
865 | { | 869 | { |
866 | uint32_t bpp, hfp_wc, hbp_wc, hsa_wc; | 870 | uint32_t bpp, hfp_wc, hbp_wc, hsa_wc, wc; |
867 | uint32_t mdresol = 0, mvporch = 0, mhporch = 0, msync = 0; | 871 | uint32_t mdresol = 0, mvporch = 0, mhporch = 0, msync = 0; |
868 | struct videomode *vmode = &dsim->vmode; | 872 | struct videomode *vmode = &dsim->vmode; |
869 | 873 | ||
870 | mdresol |= MDRESOL_SET_MAINVRESOL(vmode->vactive) | | 874 | mdresol |= MDRESOL_SET_MAINVRESOL(vmode->vactive) | |
871 | MDRESOL_SET_MAINHRESOL(vmode->hactive); | 875 | MDRESOL_SET_MAINHRESOL(vmode->hactive); |
872 | dsim_write(dsim, mdresol, DSIM_MDRESOL); | 876 | dsim_write(dsim, mdresol, DSIM_MDRESOL); |
873 | 877 | ||
874 | mvporch |= MVPORCH_SET_MAINVBP(vmode->vback_porch) | | 878 | mvporch |= MVPORCH_SET_MAINVBP(vmode->vback_porch) | |
875 | MVPORCH_SET_STABLEVFP(vmode->vfront_porch) | | 879 | MVPORCH_SET_STABLEVFP(vmode->vfront_porch) | |
876 | MVPORCH_SET_CMDALLOW(0x0); | 880 | MVPORCH_SET_CMDALLOW(0x0); |
877 | dsim_write(dsim, mvporch, DSIM_MVPORCH); | 881 | dsim_write(dsim, mvporch, DSIM_MVPORCH); |
878 | 882 | ||
879 | bpp = mipi_dsi_pixel_format_to_bpp(dsim->format); | 883 | bpp = mipi_dsi_pixel_format_to_bpp(dsim->format); |
880 | 884 | ||
881 | /* calculate hfp & hbp word counts */ | 885 | /* calculate hfp & hbp word counts */ |
882 | if (dsim->panel || !dsim->hpar) { | 886 | if (dsim->panel || !dsim->hpar) { |
883 | hfp_wc = vmode->hfront_porch * (bpp >> 3); | 887 | wc = DIV_ROUND_UP(vmode->hfront_porch * (bpp >> 3), |
884 | hbp_wc = vmode->hback_porch * (bpp >> 3); | 888 | dsim->lanes); |
889 | hfp_wc = wc > MIPI_HFP_PKT_OVERHEAD ? | ||
890 | wc - MIPI_HFP_PKT_OVERHEAD : vmode->hfront_porch; | ||
891 | wc = DIV_ROUND_UP(vmode->hback_porch * (bpp >> 3), | ||
892 | dsim->lanes); | ||
893 | hbp_wc = wc > MIPI_HBP_PKT_OVERHEAD ? | ||
894 | wc - MIPI_HBP_PKT_OVERHEAD : vmode->hback_porch; | ||
885 | } else { | 895 | } else { |
886 | hfp_wc = dsim->hpar->hfp_wc; | 896 | hfp_wc = dsim->hpar->hfp_wc; |
887 | hbp_wc = dsim->hpar->hbp_wc; | 897 | hbp_wc = dsim->hpar->hbp_wc; |
888 | } | 898 | } |
889 | 899 | ||
890 | mhporch |= MHPORCH_SET_MAINHFP(hfp_wc) | | 900 | mhporch |= MHPORCH_SET_MAINHFP(hfp_wc) | |
891 | MHPORCH_SET_MAINHBP(hbp_wc); | 901 | MHPORCH_SET_MAINHBP(hbp_wc); |
892 | 902 | ||
893 | dsim_write(dsim, mhporch, DSIM_MHPORCH); | 903 | dsim_write(dsim, mhporch, DSIM_MHPORCH); |
894 | 904 | ||
895 | /* calculate hsa word counts */ | 905 | /* calculate hsa word counts */ |
896 | if (dsim->panel || !dsim->hpar) | 906 | if (dsim->panel || !dsim->hpar) { |
897 | hsa_wc = vmode->hsync_len * (bpp >> 3); | 907 | wc = DIV_ROUND_UP(vmode->hsync_len * (bpp >> 3), |
898 | else | 908 | dsim->lanes); |
909 | hsa_wc = wc > MIPI_HSA_PKT_OVERHEAD ? | ||
910 | wc - MIPI_HSA_PKT_OVERHEAD : vmode->hsync_len; | ||
911 | } else | ||
899 | hsa_wc = dsim->hpar->hsa_wc; | 912 | hsa_wc = dsim->hpar->hsa_wc; |
900 | 913 | ||
901 | msync |= MSYNC_SET_MAINVSA(vmode->vsync_len) | | 914 | msync |= MSYNC_SET_MAINVSA(vmode->vsync_len) | |
902 | MSYNC_SET_MAINHSA(hsa_wc); | 915 | MSYNC_SET_MAINHSA(hsa_wc); |
903 | 916 | ||
904 | dsim_write(dsim, msync, DSIM_MSYNC); | 917 | dsim_write(dsim, msync, DSIM_MSYNC); |
905 | } | 918 | } |
906 | 919 | ||
907 | static void sec_mipi_dsim_config_dpi(struct sec_mipi_dsim *dsim) | 920 | static void sec_mipi_dsim_config_dpi(struct sec_mipi_dsim *dsim) |
908 | { | 921 | { |
909 | uint32_t config = 0, rgb_status = 0, data_lanes_en; | 922 | uint32_t config = 0, rgb_status = 0, data_lanes_en; |
910 | 923 | ||
911 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO) | 924 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO) |
912 | rgb_status &= ~RGB_STATUS_CMDMODE_INSEL; | 925 | rgb_status &= ~RGB_STATUS_CMDMODE_INSEL; |
913 | else | 926 | else |
914 | rgb_status |= RGB_STATUS_CMDMODE_INSEL; | 927 | rgb_status |= RGB_STATUS_CMDMODE_INSEL; |
915 | 928 | ||
916 | dsim_write(dsim, rgb_status, DSIM_RGB_STATUS); | 929 | dsim_write(dsim, rgb_status, DSIM_RGB_STATUS); |
917 | 930 | ||
918 | if (dsim->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) { | 931 | if (dsim->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) { |
919 | config |= CONFIG_NON_CONTINUOUS_CLOCK_LANE; | 932 | config |= CONFIG_NON_CONTINUOUS_CLOCK_LANE; |
920 | config |= CONFIG_CLKLANE_STOP_START; | 933 | config |= CONFIG_CLKLANE_STOP_START; |
921 | } | 934 | } |
922 | 935 | ||
923 | if (dsim->mode_flags & MIPI_DSI_MODE_VSYNC_FLUSH) | 936 | if (dsim->mode_flags & MIPI_DSI_MODE_VSYNC_FLUSH) |
924 | config |= CONFIG_MFLUSH_VS; | 937 | config |= CONFIG_MFLUSH_VS; |
925 | 938 | ||
926 | /* disable EoT packets in HS mode */ | 939 | /* disable EoT packets in HS mode */ |
927 | if (dsim->mode_flags & MIPI_DSI_MODE_EOT_PACKET) | 940 | if (dsim->mode_flags & MIPI_DSI_MODE_EOT_PACKET) |
928 | config |= CONFIG_EOT_R03; | 941 | config |= CONFIG_EOT_R03; |
929 | 942 | ||
930 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO) { | 943 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO) { |
931 | config |= CONFIG_VIDEOMODE; | 944 | config |= CONFIG_VIDEOMODE; |
932 | 945 | ||
933 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) | 946 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) |
934 | config |= CONFIG_BURSTMODE; | 947 | config |= CONFIG_BURSTMODE; |
935 | 948 | ||
936 | else if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) | 949 | else if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) |
937 | config |= CONFIG_SYNCINFORM; | 950 | config |= CONFIG_SYNCINFORM; |
938 | 951 | ||
939 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_AUTO_VERT) | 952 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_AUTO_VERT) |
940 | config |= CONFIG_AUTOMODE; | 953 | config |= CONFIG_AUTOMODE; |
941 | 954 | ||
942 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_HSE) | 955 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_HSE) |
943 | config |= CONFIG_HSEDISABLEMODE; | 956 | config |= CONFIG_HSEDISABLEMODE; |
944 | 957 | ||
945 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_HFP) | 958 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_HFP) |
946 | config |= CONFIG_HFPDISABLEMODE; | 959 | config |= CONFIG_HFPDISABLEMODE; |
947 | 960 | ||
948 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_HBP) | 961 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_HBP) |
949 | config |= CONFIG_HBPDISABLEMODE; | 962 | config |= CONFIG_HBPDISABLEMODE; |
950 | 963 | ||
951 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_HSA) | 964 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_HSA) |
952 | config |= CONFIG_HSADISABLEMODE; | 965 | config |= CONFIG_HSADISABLEMODE; |
953 | } | 966 | } |
954 | 967 | ||
955 | config |= CONFIG_SET_MAINVC(dsim->channel); | 968 | config |= CONFIG_SET_MAINVC(dsim->channel); |
956 | 969 | ||
957 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO) { | 970 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO) { |
958 | switch (dsim->format) { | 971 | switch (dsim->format) { |
959 | case MIPI_DSI_FMT_RGB565: | 972 | case MIPI_DSI_FMT_RGB565: |
960 | config |= CONFIG_SET_MAINPIXFORMAT(0x4); | 973 | config |= CONFIG_SET_MAINPIXFORMAT(0x4); |
961 | break; | 974 | break; |
962 | case MIPI_DSI_FMT_RGB666_PACKED: | 975 | case MIPI_DSI_FMT_RGB666_PACKED: |
963 | config |= CONFIG_SET_MAINPIXFORMAT(0x5); | 976 | config |= CONFIG_SET_MAINPIXFORMAT(0x5); |
964 | break; | 977 | break; |
965 | case MIPI_DSI_FMT_RGB666: | 978 | case MIPI_DSI_FMT_RGB666: |
966 | config |= CONFIG_SET_MAINPIXFORMAT(0x6); | 979 | config |= CONFIG_SET_MAINPIXFORMAT(0x6); |
967 | break; | 980 | break; |
968 | case MIPI_DSI_FMT_RGB888: | 981 | case MIPI_DSI_FMT_RGB888: |
969 | config |= CONFIG_SET_MAINPIXFORMAT(0x7); | 982 | config |= CONFIG_SET_MAINPIXFORMAT(0x7); |
970 | break; | 983 | break; |
971 | default: | 984 | default: |
972 | config |= CONFIG_SET_MAINPIXFORMAT(0x7); | 985 | config |= CONFIG_SET_MAINPIXFORMAT(0x7); |
973 | break; | 986 | break; |
974 | } | 987 | } |
975 | } | 988 | } |
976 | 989 | ||
977 | /* config data lanes number and enable lanes */ | 990 | /* config data lanes number and enable lanes */ |
978 | data_lanes_en = (0x1 << dsim->lanes) - 1; | 991 | data_lanes_en = (0x1 << dsim->lanes) - 1; |
979 | config |= CONFIG_SET_NUMOFDATLANE(dsim->lanes - 1); | 992 | config |= CONFIG_SET_NUMOFDATLANE(dsim->lanes - 1); |
980 | config |= CONFIG_SET_LANEEN(0x1 | data_lanes_en << 1); | 993 | config |= CONFIG_SET_LANEEN(0x1 | data_lanes_en << 1); |
981 | 994 | ||
982 | dsim_write(dsim, config, DSIM_CONFIG); | 995 | dsim_write(dsim, config, DSIM_CONFIG); |
983 | } | 996 | } |
984 | 997 | ||
985 | static void sec_mipi_dsim_config_dphy(struct sec_mipi_dsim *dsim) | 998 | static void sec_mipi_dsim_config_dphy(struct sec_mipi_dsim *dsim) |
986 | { | 999 | { |
987 | struct sec_mipi_dsim_dphy_timing key = { 0 }; | 1000 | struct sec_mipi_dsim_dphy_timing key = { 0 }; |
988 | const struct sec_mipi_dsim_dphy_timing *match = NULL; | 1001 | const struct sec_mipi_dsim_dphy_timing *match = NULL; |
989 | const struct sec_mipi_dsim_plat_data *pdata = dsim->pdata; | 1002 | const struct sec_mipi_dsim_plat_data *pdata = dsim->pdata; |
990 | uint32_t phytiming = 0, phytiming1 = 0, phytiming2 = 0, timeout = 0; | 1003 | uint32_t phytiming = 0, phytiming1 = 0, phytiming2 = 0, timeout = 0; |
991 | uint32_t hactive, vactive; | 1004 | uint32_t hactive, vactive; |
992 | struct videomode *vmode = &dsim->vmode; | 1005 | struct videomode *vmode = &dsim->vmode; |
993 | struct drm_display_mode mode; | 1006 | struct drm_display_mode mode; |
994 | 1007 | ||
995 | key.bit_clk = DIV_ROUND_CLOSEST_ULL(dsim->bit_clk, 1000); | 1008 | key.bit_clk = DIV_ROUND_CLOSEST_ULL(dsim->bit_clk, 1000); |
996 | 1009 | ||
997 | /* '1280x720@60Hz' mode with 2 data lanes | 1010 | /* '1280x720@60Hz' mode with 2 data lanes |
998 | * requires special fine tuning for DPHY | 1011 | * requires special fine tuning for DPHY |
999 | * TIMING config according to the tests. | 1012 | * TIMING config according to the tests. |
1000 | */ | 1013 | */ |
1001 | if (dsim->lanes == 2) { | 1014 | if (dsim->lanes == 2) { |
1002 | hactive = vmode->hactive; | 1015 | hactive = vmode->hactive; |
1003 | vactive = vmode->vactive; | 1016 | vactive = vmode->vactive; |
1004 | 1017 | ||
1005 | if (hactive == 1280 && vactive == 720) { | 1018 | if (hactive == 1280 && vactive == 720) { |
1006 | memset(&mode, 0x0, sizeof(mode)); | 1019 | memset(&mode, 0x0, sizeof(mode)); |
1007 | drm_display_mode_from_videomode(vmode, &mode); | 1020 | drm_display_mode_from_videomode(vmode, &mode); |
1008 | 1021 | ||
1009 | if (drm_mode_vrefresh(&mode) == 60) | 1022 | if (drm_mode_vrefresh(&mode) == 60) |
1010 | key.bit_clk >>= 1; | 1023 | key.bit_clk >>= 1; |
1011 | } | 1024 | } |
1012 | } | 1025 | } |
1013 | 1026 | ||
1014 | match = bsearch(&key, pdata->dphy_timing, pdata->num_dphy_timing, | 1027 | match = bsearch(&key, pdata->dphy_timing, pdata->num_dphy_timing, |
1015 | sizeof(struct sec_mipi_dsim_dphy_timing), | 1028 | sizeof(struct sec_mipi_dsim_dphy_timing), |
1016 | pdata->dphy_timing_cmp); | 1029 | pdata->dphy_timing_cmp); |
1017 | if (WARN_ON(!match)) | 1030 | if (WARN_ON(!match)) |
1018 | return; | 1031 | return; |
1019 | 1032 | ||
1020 | phytiming |= PHYTIMING_SET_M_TLPXCTL(match->lpx) | | 1033 | phytiming |= PHYTIMING_SET_M_TLPXCTL(match->lpx) | |
1021 | PHYTIMING_SET_M_THSEXITCTL(match->hs_exit); | 1034 | PHYTIMING_SET_M_THSEXITCTL(match->hs_exit); |
1022 | dsim_write(dsim, phytiming, DSIM_PHYTIMING); | 1035 | dsim_write(dsim, phytiming, DSIM_PHYTIMING); |
1023 | 1036 | ||
1024 | phytiming1 |= PHYTIMING1_SET_M_TCLKPRPRCTL(match->clk_prepare) | | 1037 | phytiming1 |= PHYTIMING1_SET_M_TCLKPRPRCTL(match->clk_prepare) | |
1025 | PHYTIMING1_SET_M_TCLKZEROCTL(match->clk_zero) | | 1038 | PHYTIMING1_SET_M_TCLKZEROCTL(match->clk_zero) | |
1026 | PHYTIMING1_SET_M_TCLKPOSTCTL(match->clk_post) | | 1039 | PHYTIMING1_SET_M_TCLKPOSTCTL(match->clk_post) | |
1027 | PHYTIMING1_SET_M_TCLKTRAILCTL(match->clk_trail); | 1040 | PHYTIMING1_SET_M_TCLKTRAILCTL(match->clk_trail); |
1028 | dsim_write(dsim, phytiming1, DSIM_PHYTIMING1); | 1041 | dsim_write(dsim, phytiming1, DSIM_PHYTIMING1); |
1029 | 1042 | ||
1030 | phytiming2 |= PHYTIMING2_SET_M_THSPRPRCTL(match->hs_prepare) | | 1043 | phytiming2 |= PHYTIMING2_SET_M_THSPRPRCTL(match->hs_prepare) | |
1031 | PHYTIMING2_SET_M_THSZEROCTL(match->hs_zero) | | 1044 | PHYTIMING2_SET_M_THSZEROCTL(match->hs_zero) | |
1032 | PHYTIMING2_SET_M_THSTRAILCTL(match->hs_trail); | 1045 | PHYTIMING2_SET_M_THSTRAILCTL(match->hs_trail); |
1033 | dsim_write(dsim, phytiming2, DSIM_PHYTIMING2); | 1046 | dsim_write(dsim, phytiming2, DSIM_PHYTIMING2); |
1034 | 1047 | ||
1035 | timeout |= TIMEOUT_SET_BTAOUT(0xff) | | 1048 | timeout |= TIMEOUT_SET_BTAOUT(0xff) | |
1036 | TIMEOUT_SET_LPDRTOUT(0xff); | 1049 | TIMEOUT_SET_LPDRTOUT(0xff); |
1037 | dsim_write(dsim, timeout, DSIM_TIMEOUT); | 1050 | dsim_write(dsim, timeout, DSIM_TIMEOUT); |
1038 | } | 1051 | } |
1039 | 1052 | ||
1040 | static void sec_mipi_dsim_init_fifo_pointers(struct sec_mipi_dsim *dsim) | 1053 | static void sec_mipi_dsim_init_fifo_pointers(struct sec_mipi_dsim *dsim) |
1041 | { | 1054 | { |
1042 | uint32_t fifoctrl, fifo_ptrs; | 1055 | uint32_t fifoctrl, fifo_ptrs; |
1043 | 1056 | ||
1044 | fifoctrl = dsim_read(dsim, DSIM_FIFOCTRL); | 1057 | fifoctrl = dsim_read(dsim, DSIM_FIFOCTRL); |
1045 | 1058 | ||
1046 | fifo_ptrs = FIFOCTRL_NINITRX | | 1059 | fifo_ptrs = FIFOCTRL_NINITRX | |
1047 | FIFOCTRL_NINITSFR | | 1060 | FIFOCTRL_NINITSFR | |
1048 | FIFOCTRL_NINITI80 | | 1061 | FIFOCTRL_NINITI80 | |
1049 | FIFOCTRL_NINITSUB | | 1062 | FIFOCTRL_NINITSUB | |
1050 | FIFOCTRL_NINITMAIN; | 1063 | FIFOCTRL_NINITMAIN; |
1051 | 1064 | ||
1052 | fifoctrl &= ~fifo_ptrs; | 1065 | fifoctrl &= ~fifo_ptrs; |
1053 | dsim_write(dsim, fifoctrl, DSIM_FIFOCTRL); | 1066 | dsim_write(dsim, fifoctrl, DSIM_FIFOCTRL); |
1054 | udelay(500); | 1067 | udelay(500); |
1055 | 1068 | ||
1056 | fifoctrl |= fifo_ptrs; | 1069 | fifoctrl |= fifo_ptrs; |
1057 | dsim_write(dsim, fifoctrl, DSIM_FIFOCTRL); | 1070 | dsim_write(dsim, fifoctrl, DSIM_FIFOCTRL); |
1058 | udelay(500); | 1071 | udelay(500); |
1059 | } | 1072 | } |
1060 | 1073 | ||
1061 | static void sec_mipi_dsim_config_clkctrl(struct sec_mipi_dsim *dsim) | 1074 | static void sec_mipi_dsim_config_clkctrl(struct sec_mipi_dsim *dsim) |
1062 | { | 1075 | { |
1063 | uint32_t clkctrl = 0, data_lanes_en; | 1076 | uint32_t clkctrl = 0, data_lanes_en; |
1064 | uint32_t byte_clk, esc_prescaler; | 1077 | uint32_t byte_clk, esc_prescaler; |
1065 | 1078 | ||
1066 | clkctrl |= CLKCTRL_TXREQUESTHSCLK; | 1079 | clkctrl |= CLKCTRL_TXREQUESTHSCLK; |
1067 | 1080 | ||
1068 | /* using 1.5Gbps PHY */ | 1081 | /* using 1.5Gbps PHY */ |
1069 | clkctrl |= CLKCTRL_DPHY_SEL_1P5G; | 1082 | clkctrl |= CLKCTRL_DPHY_SEL_1P5G; |
1070 | 1083 | ||
1071 | clkctrl |= CLKCTRL_ESCCLKEN; | 1084 | clkctrl |= CLKCTRL_ESCCLKEN; |
1072 | 1085 | ||
1073 | clkctrl &= ~CLKCTRL_PLLBYPASS; | 1086 | clkctrl &= ~CLKCTRL_PLLBYPASS; |
1074 | 1087 | ||
1075 | clkctrl |= CLKCTRL_BYTECLKSRC_DPHY_PLL; | 1088 | clkctrl |= CLKCTRL_BYTECLKSRC_DPHY_PLL; |
1076 | 1089 | ||
1077 | clkctrl |= CLKCTRL_BYTECLKEN; | 1090 | clkctrl |= CLKCTRL_BYTECLKEN; |
1078 | 1091 | ||
1079 | data_lanes_en = (0x1 << dsim->lanes) - 1; | 1092 | data_lanes_en = (0x1 << dsim->lanes) - 1; |
1080 | clkctrl |= CLKCTRL_SET_LANEESCCLKEN(0x1 | data_lanes_en << 1); | 1093 | clkctrl |= CLKCTRL_SET_LANEESCCLKEN(0x1 | data_lanes_en << 1); |
1081 | 1094 | ||
1082 | /* calculate esc prescaler from byte clock: | 1095 | /* calculate esc prescaler from byte clock: |
1083 | * EscClk = ByteClk / EscPrescaler; | 1096 | * EscClk = ByteClk / EscPrescaler; |
1084 | */ | 1097 | */ |
1085 | byte_clk = dsim->bit_clk >> 3; | 1098 | byte_clk = dsim->bit_clk >> 3; |
1086 | esc_prescaler = DIV_ROUND_UP(byte_clk, MAX_ESC_CLK_FREQ); | 1099 | esc_prescaler = DIV_ROUND_UP(byte_clk, MAX_ESC_CLK_FREQ); |
1087 | clkctrl |= CLKCTRL_SET_ESCPRESCALER(esc_prescaler); | 1100 | clkctrl |= CLKCTRL_SET_ESCPRESCALER(esc_prescaler); |
1088 | 1101 | ||
1089 | dsim_write(dsim, clkctrl, DSIM_CLKCTRL); | 1102 | dsim_write(dsim, clkctrl, DSIM_CLKCTRL); |
1090 | } | 1103 | } |
1091 | 1104 | ||
1092 | static void sec_mipi_dsim_set_standby(struct sec_mipi_dsim *dsim, | 1105 | static void sec_mipi_dsim_set_standby(struct sec_mipi_dsim *dsim, |
1093 | bool standby) | 1106 | bool standby) |
1094 | { | 1107 | { |
1095 | uint32_t mdresol = 0; | 1108 | uint32_t mdresol = 0; |
1096 | 1109 | ||
1097 | mdresol = dsim_read(dsim, DSIM_MDRESOL); | 1110 | mdresol = dsim_read(dsim, DSIM_MDRESOL); |
1098 | 1111 | ||
1099 | if (standby) | 1112 | if (standby) |
1100 | mdresol |= MDRESOL_MAINSTANDBY; | 1113 | mdresol |= MDRESOL_MAINSTANDBY; |
1101 | else | 1114 | else |
1102 | mdresol &= ~MDRESOL_MAINSTANDBY; | 1115 | mdresol &= ~MDRESOL_MAINSTANDBY; |
1103 | 1116 | ||
1104 | dsim_write(dsim, mdresol, DSIM_MDRESOL); | 1117 | dsim_write(dsim, mdresol, DSIM_MDRESOL); |
1105 | } | 1118 | } |
1106 | 1119 | ||
1107 | int sec_mipi_dsim_check_pll_out(void *driver_private, | 1120 | int sec_mipi_dsim_check_pll_out(void *driver_private, |
1108 | const struct drm_display_mode *mode) | 1121 | const struct drm_display_mode *mode) |
1109 | { | 1122 | { |
1110 | int bpp; | 1123 | int bpp; |
1111 | uint32_t pix_clk, bit_clk, ref_clk; | 1124 | uint32_t pix_clk, bit_clk, ref_clk; |
1112 | struct sec_mipi_dsim *dsim = driver_private; | 1125 | struct sec_mipi_dsim *dsim = driver_private; |
1113 | const struct sec_mipi_dsim_plat_data *pdata = dsim->pdata; | 1126 | const struct sec_mipi_dsim_plat_data *pdata = dsim->pdata; |
1114 | const struct dsim_hblank_par *hpar; | 1127 | const struct dsim_hblank_par *hpar; |
1115 | const struct dsim_pll_pms *pms; | 1128 | const struct dsim_pll_pms *pms; |
1116 | 1129 | ||
1117 | bpp = mipi_dsi_pixel_format_to_bpp(dsim->format); | 1130 | bpp = mipi_dsi_pixel_format_to_bpp(dsim->format); |
1118 | if (bpp < 0) | 1131 | if (bpp < 0) |
1119 | return -EINVAL; | 1132 | return -EINVAL; |
1120 | 1133 | ||
1121 | pix_clk = mode->clock; | 1134 | pix_clk = mode->clock; |
1122 | bit_clk = DIV_ROUND_UP(pix_clk * bpp, dsim->lanes); | 1135 | bit_clk = DIV_ROUND_UP(pix_clk * bpp, dsim->lanes); |
1123 | 1136 | ||
1124 | if (bit_clk * 1000 > pdata->max_data_rate) { | 1137 | if (bit_clk * 1000 > pdata->max_data_rate) { |
1125 | dev_err(dsim->dev, | 1138 | dev_err(dsim->dev, |
1126 | "reuest bit clk freq exceeds lane's maximum value\n"); | 1139 | "reuest bit clk freq exceeds lane's maximum value\n"); |
1127 | return -EINVAL; | 1140 | return -EINVAL; |
1128 | } | 1141 | } |
1129 | 1142 | ||
1130 | dsim->pix_clk = pix_clk; | 1143 | dsim->pix_clk = pix_clk; |
1131 | dsim->bit_clk = bit_clk; | 1144 | dsim->bit_clk = bit_clk; |
1132 | 1145 | ||
1133 | dsim->pms = 0x4210; | 1146 | dsim->pms = 0x4210; |
1134 | dsim->hpar = NULL; | 1147 | dsim->hpar = NULL; |
1135 | if (dsim->panel) | 1148 | if (dsim->panel) |
1136 | return 0; | 1149 | return 0; |
1137 | 1150 | ||
1138 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { | 1151 | if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { |
1139 | hpar = sec_mipi_dsim_get_hblank_par(mode->name, | 1152 | hpar = sec_mipi_dsim_get_hblank_par(mode->name, |
1140 | mode->vrefresh, | 1153 | mode->vrefresh, |
1141 | dsim->lanes); | 1154 | dsim->lanes); |
1142 | if (!hpar) | 1155 | if (!hpar) |
1143 | return -EINVAL; | 1156 | return -EINVAL; |
1144 | dsim->hpar = hpar; | 1157 | dsim->hpar = hpar; |
1145 | 1158 | ||
1146 | pms = sec_mipi_dsim_get_pms(dsim->bit_clk); | 1159 | pms = sec_mipi_dsim_get_pms(dsim->bit_clk); |
1147 | if (WARN_ON(!pms)) | 1160 | if (WARN_ON(!pms)) |
1148 | return -EINVAL; | 1161 | return -EINVAL; |
1149 | 1162 | ||
1150 | ref_clk = PHY_REF_CLK / 1000; | 1163 | ref_clk = PHY_REF_CLK / 1000; |
1151 | /* TODO: add PMS calculate and check | 1164 | /* TODO: add PMS calculate and check |
1152 | * Only support '1080p@60Hz' for now, | 1165 | * Only support '1080p@60Hz' for now, |
1153 | * add other modes support later | 1166 | * add other modes support later |
1154 | */ | 1167 | */ |
1155 | dsim->pms = PLLCTRL_SET_P(pms->p) | | 1168 | dsim->pms = PLLCTRL_SET_P(pms->p) | |
1156 | PLLCTRL_SET_M(pms->m) | | 1169 | PLLCTRL_SET_M(pms->m) | |
1157 | PLLCTRL_SET_S(pms->s); | 1170 | PLLCTRL_SET_S(pms->s); |
1158 | } | 1171 | } |
1159 | 1172 | ||
1160 | return 0; | 1173 | return 0; |
1161 | } | 1174 | } |
1162 | EXPORT_SYMBOL(sec_mipi_dsim_check_pll_out); | 1175 | EXPORT_SYMBOL(sec_mipi_dsim_check_pll_out); |
1163 | 1176 | ||
1164 | static void sec_mipi_dsim_bridge_enable(struct drm_bridge *bridge) | 1177 | static void sec_mipi_dsim_bridge_enable(struct drm_bridge *bridge) |
1165 | { | 1178 | { |
1166 | int ret; | 1179 | int ret; |
1167 | struct sec_mipi_dsim *dsim = bridge->driver_private; | 1180 | struct sec_mipi_dsim *dsim = bridge->driver_private; |
1168 | 1181 | ||
1169 | /* At this moment, the dsim bridge's preceding encoder has | 1182 | /* At this moment, the dsim bridge's preceding encoder has |
1170 | * already been enabled. So the dsim can be configed here | 1183 | * already been enabled. So the dsim can be configed here |
1171 | */ | 1184 | */ |
1172 | 1185 | ||
1173 | /* config main display mode */ | 1186 | /* config main display mode */ |
1174 | sec_mipi_dsim_set_main_mode(dsim); | 1187 | sec_mipi_dsim_set_main_mode(dsim); |
1175 | 1188 | ||
1176 | /* config dsim dpi */ | 1189 | /* config dsim dpi */ |
1177 | sec_mipi_dsim_config_dpi(dsim); | 1190 | sec_mipi_dsim_config_dpi(dsim); |
1178 | 1191 | ||
1179 | /* config dsim pll */ | 1192 | /* config dsim pll */ |
1180 | ret = sec_mipi_dsim_config_pll(dsim); | 1193 | ret = sec_mipi_dsim_config_pll(dsim); |
1181 | if (ret) { | 1194 | if (ret) { |
1182 | dev_err(dsim->dev, "dsim pll config failed: %d\n", ret); | 1195 | dev_err(dsim->dev, "dsim pll config failed: %d\n", ret); |
1183 | return; | 1196 | return; |
1184 | } | 1197 | } |
1185 | 1198 | ||
1186 | /* config dphy timings */ | 1199 | /* config dphy timings */ |
1187 | sec_mipi_dsim_config_dphy(dsim); | 1200 | sec_mipi_dsim_config_dphy(dsim); |
1188 | 1201 | ||
1189 | /* initialize FIFO pointers */ | 1202 | /* initialize FIFO pointers */ |
1190 | sec_mipi_dsim_init_fifo_pointers(dsim); | 1203 | sec_mipi_dsim_init_fifo_pointers(dsim); |
1191 | 1204 | ||
1192 | /* prepare panel if exists */ | 1205 | /* prepare panel if exists */ |
1193 | if (dsim->panel) { | 1206 | if (dsim->panel) { |
1194 | ret = drm_panel_prepare(dsim->panel); | 1207 | ret = drm_panel_prepare(dsim->panel); |
1195 | if (unlikely(ret)) { | 1208 | if (unlikely(ret)) { |
1196 | dev_err(dsim->dev, "panel prepare failed: %d\n", ret); | 1209 | dev_err(dsim->dev, "panel prepare failed: %d\n", ret); |
1197 | return; | 1210 | return; |
1198 | } | 1211 | } |
1199 | } | 1212 | } |
1200 | 1213 | ||
1201 | /* config esc clock, byte clock and etc */ | 1214 | /* config esc clock, byte clock and etc */ |
1202 | sec_mipi_dsim_config_clkctrl(dsim); | 1215 | sec_mipi_dsim_config_clkctrl(dsim); |
1203 | 1216 | ||
1204 | /* enable panel if exists */ | 1217 | /* enable panel if exists */ |
1205 | if (dsim->panel) { | 1218 | if (dsim->panel) { |
1206 | ret = drm_panel_enable(dsim->panel); | 1219 | ret = drm_panel_enable(dsim->panel); |
1207 | if (unlikely(ret)) { | 1220 | if (unlikely(ret)) { |
1208 | dev_err(dsim->dev, "panel enable failed: %d\n", ret); | 1221 | dev_err(dsim->dev, "panel enable failed: %d\n", ret); |
1209 | goto panel_unprepare; | 1222 | goto panel_unprepare; |
1210 | } | 1223 | } |
1211 | } | 1224 | } |
1212 | 1225 | ||
1213 | /* enable data transfer of dsim */ | 1226 | /* enable data transfer of dsim */ |
1214 | sec_mipi_dsim_set_standby(dsim, true); | 1227 | sec_mipi_dsim_set_standby(dsim, true); |
1215 | 1228 | ||
1216 | return; | 1229 | return; |
1217 | 1230 | ||
1218 | panel_unprepare: | 1231 | panel_unprepare: |
1219 | ret = drm_panel_unprepare(dsim->panel); | 1232 | ret = drm_panel_unprepare(dsim->panel); |
1220 | if (unlikely(ret)) | 1233 | if (unlikely(ret)) |
1221 | dev_err(dsim->dev, "panel unprepare failed: %d\n", ret); | 1234 | dev_err(dsim->dev, "panel unprepare failed: %d\n", ret); |
1222 | } | 1235 | } |
1223 | 1236 | ||
1224 | static void sec_mipi_dsim_disable_clkctrl(struct sec_mipi_dsim *dsim) | 1237 | static void sec_mipi_dsim_disable_clkctrl(struct sec_mipi_dsim *dsim) |
1225 | { | 1238 | { |
1226 | uint32_t clkctrl; | 1239 | uint32_t clkctrl; |
1227 | 1240 | ||
1228 | clkctrl = dsim_read(dsim, DSIM_CLKCTRL); | 1241 | clkctrl = dsim_read(dsim, DSIM_CLKCTRL); |
1229 | 1242 | ||
1230 | clkctrl &= ~CLKCTRL_TXREQUESTHSCLK; | 1243 | clkctrl &= ~CLKCTRL_TXREQUESTHSCLK; |
1231 | 1244 | ||
1232 | clkctrl &= ~CLKCTRL_ESCCLKEN; | 1245 | clkctrl &= ~CLKCTRL_ESCCLKEN; |
1233 | 1246 | ||
1234 | clkctrl &= ~CLKCTRL_BYTECLKEN; | 1247 | clkctrl &= ~CLKCTRL_BYTECLKEN; |
1235 | 1248 | ||
1236 | dsim_write(dsim, clkctrl, DSIM_CLKCTRL); | 1249 | dsim_write(dsim, clkctrl, DSIM_CLKCTRL); |
1237 | } | 1250 | } |
1238 | 1251 | ||
1239 | static void sec_mipi_dsim_disable_pll(struct sec_mipi_dsim *dsim) | 1252 | static void sec_mipi_dsim_disable_pll(struct sec_mipi_dsim *dsim) |
1240 | { | 1253 | { |
1241 | uint32_t pllctrl; | 1254 | uint32_t pllctrl; |
1242 | 1255 | ||
1243 | pllctrl = dsim_read(dsim, DSIM_PLLCTRL); | 1256 | pllctrl = dsim_read(dsim, DSIM_PLLCTRL); |
1244 | 1257 | ||
1245 | pllctrl &= ~PLLCTRL_PLLEN; | 1258 | pllctrl &= ~PLLCTRL_PLLEN; |
1246 | 1259 | ||
1247 | dsim_write(dsim, pllctrl, DSIM_PLLCTRL); | 1260 | dsim_write(dsim, pllctrl, DSIM_PLLCTRL); |
1248 | } | 1261 | } |
1249 | 1262 | ||
1250 | static void sec_mipi_dsim_bridge_disable(struct drm_bridge *bridge) | 1263 | static void sec_mipi_dsim_bridge_disable(struct drm_bridge *bridge) |
1251 | { | 1264 | { |
1252 | int ret; | 1265 | int ret; |
1253 | struct sec_mipi_dsim *dsim = bridge->driver_private; | 1266 | struct sec_mipi_dsim *dsim = bridge->driver_private; |
1254 | 1267 | ||
1255 | /* disable panel if exists */ | 1268 | /* disable panel if exists */ |
1256 | if (dsim->panel) { | 1269 | if (dsim->panel) { |
1257 | ret = drm_panel_disable(dsim->panel); | 1270 | ret = drm_panel_disable(dsim->panel); |
1258 | if (unlikely(ret)) | 1271 | if (unlikely(ret)) |
1259 | dev_err(dsim->dev, "panel disable failed: %d\n", ret); | 1272 | dev_err(dsim->dev, "panel disable failed: %d\n", ret); |
1260 | } | 1273 | } |
1261 | 1274 | ||
1262 | /* disable data transfer of dsim */ | 1275 | /* disable data transfer of dsim */ |
1263 | sec_mipi_dsim_set_standby(dsim, false); | 1276 | sec_mipi_dsim_set_standby(dsim, false); |
1264 | 1277 | ||
1265 | /* disable esc clock & byte clock */ | 1278 | /* disable esc clock & byte clock */ |
1266 | sec_mipi_dsim_disable_clkctrl(dsim); | 1279 | sec_mipi_dsim_disable_clkctrl(dsim); |
1267 | 1280 | ||
1268 | /* disable dsim pll */ | 1281 | /* disable dsim pll */ |
1269 | sec_mipi_dsim_disable_pll(dsim); | 1282 | sec_mipi_dsim_disable_pll(dsim); |
1270 | 1283 | ||
1271 | /* unprepare panel if exists */ | 1284 | /* unprepare panel if exists */ |
1272 | if (dsim->panel) { | 1285 | if (dsim->panel) { |
1273 | ret = drm_panel_unprepare(dsim->panel); | 1286 | ret = drm_panel_unprepare(dsim->panel); |
1274 | if (unlikely(ret)) | 1287 | if (unlikely(ret)) |
1275 | dev_err(dsim->dev, "panel unprepare failed: %d\n", ret); | 1288 | dev_err(dsim->dev, "panel unprepare failed: %d\n", ret); |
1276 | } | 1289 | } |
1277 | } | 1290 | } |
1278 | 1291 | ||
1279 | static bool sec_mipi_dsim_bridge_mode_fixup(struct drm_bridge *bridge, | 1292 | static bool sec_mipi_dsim_bridge_mode_fixup(struct drm_bridge *bridge, |
1280 | const struct drm_display_mode *mode, | 1293 | const struct drm_display_mode *mode, |
1281 | struct drm_display_mode *adjusted_mode) | 1294 | struct drm_display_mode *adjusted_mode) |
1282 | { | 1295 | { |
1283 | int private_flags; | 1296 | int private_flags; |
1284 | struct sec_mipi_dsim *dsim = bridge->driver_private; | 1297 | struct sec_mipi_dsim *dsim = bridge->driver_private; |
1285 | 1298 | ||
1286 | /* Since mipi dsi cannot do color conversion, | 1299 | /* Since mipi dsi cannot do color conversion, |
1287 | * so the pixel format output by mipi dsi should | 1300 | * so the pixel format output by mipi dsi should |
1288 | * be the same with the pixel format recieved by | 1301 | * be the same with the pixel format recieved by |
1289 | * mipi dsi. And the pixel format information needs | 1302 | * mipi dsi. And the pixel format information needs |
1290 | * to be passed to CRTC to be checked with the CRTC | 1303 | * to be passed to CRTC to be checked with the CRTC |
1291 | * attached plane fb pixel format. | 1304 | * attached plane fb pixel format. |
1292 | */ | 1305 | */ |
1293 | switch (dsim->format) { | 1306 | switch (dsim->format) { |
1294 | case MIPI_DSI_FMT_RGB888: | 1307 | case MIPI_DSI_FMT_RGB888: |
1295 | private_flags = MEDIA_BUS_FMT_RGB888_1X24; | 1308 | private_flags = MEDIA_BUS_FMT_RGB888_1X24; |
1296 | break; | 1309 | break; |
1297 | case MIPI_DSI_FMT_RGB666: | 1310 | case MIPI_DSI_FMT_RGB666: |
1298 | private_flags = MEDIA_BUS_FMT_RGB666_1X24_CPADHI; | 1311 | private_flags = MEDIA_BUS_FMT_RGB666_1X24_CPADHI; |
1299 | break; | 1312 | break; |
1300 | case MIPI_DSI_FMT_RGB666_PACKED: | 1313 | case MIPI_DSI_FMT_RGB666_PACKED: |
1301 | private_flags = MEDIA_BUS_FMT_RGB666_1X18; | 1314 | private_flags = MEDIA_BUS_FMT_RGB666_1X18; |
1302 | break; | 1315 | break; |
1303 | case MIPI_DSI_FMT_RGB565: | 1316 | case MIPI_DSI_FMT_RGB565: |
1304 | private_flags = MEDIA_BUS_FMT_RGB565_1X16; | 1317 | private_flags = MEDIA_BUS_FMT_RGB565_1X16; |
1305 | break; | 1318 | break; |
1306 | default: | 1319 | default: |
1307 | return false; | 1320 | return false; |
1308 | } | 1321 | } |
1309 | 1322 | ||
1310 | adjusted_mode->private_flags = private_flags; | 1323 | adjusted_mode->private_flags = private_flags; |
1311 | 1324 | ||
1312 | /* the 'bus_flags' in connector's display_info is useless | 1325 | /* the 'bus_flags' in connector's display_info is useless |
1313 | * for mipi dsim, since dsim only sends packets with no | 1326 | * for mipi dsim, since dsim only sends packets with no |
1314 | * polarities information in the packets. But the dsim | 1327 | * polarities information in the packets. But the dsim |
1315 | * host has some polarities requirements for the CRTC: | 1328 | * host has some polarities requirements for the CRTC: |
1316 | * dsim only can accpet active high Vsync, Hsync and DE | 1329 | * dsim only can accpet active high Vsync, Hsync and DE |
1317 | * signals. | 1330 | * signals. |
1318 | */ | 1331 | */ |
1319 | if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) { | 1332 | if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) { |
1320 | adjusted_mode->flags &= ~DRM_MODE_FLAG_NHSYNC; | 1333 | adjusted_mode->flags &= ~DRM_MODE_FLAG_NHSYNC; |
1321 | adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC; | 1334 | adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC; |
1322 | } | 1335 | } |
1323 | 1336 | ||
1324 | if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) { | 1337 | if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) { |
1325 | adjusted_mode->flags &= ~DRM_MODE_FLAG_NVSYNC; | 1338 | adjusted_mode->flags &= ~DRM_MODE_FLAG_NVSYNC; |
1326 | adjusted_mode->flags |= DRM_MODE_FLAG_PVSYNC; | 1339 | adjusted_mode->flags |= DRM_MODE_FLAG_PVSYNC; |
1327 | } | 1340 | } |
1328 | 1341 | ||
1329 | return true; | 1342 | return true; |
1330 | } | 1343 | } |
1331 | 1344 | ||
1332 | static void sec_mipi_dsim_bridge_mode_set(struct drm_bridge *bridge, | 1345 | static void sec_mipi_dsim_bridge_mode_set(struct drm_bridge *bridge, |
1333 | struct drm_display_mode *mode, | 1346 | struct drm_display_mode *mode, |
1334 | struct drm_display_mode *adjusted_mode) | 1347 | struct drm_display_mode *adjusted_mode) |
1335 | { | 1348 | { |
1336 | struct sec_mipi_dsim *dsim = bridge->driver_private; | 1349 | struct sec_mipi_dsim *dsim = bridge->driver_private; |
1337 | 1350 | ||
1338 | /* This hook is called when the display pipe is completely | 1351 | /* This hook is called when the display pipe is completely |
1339 | * off. And since the pm runtime is implemented, the dsim | 1352 | * off. And since the pm runtime is implemented, the dsim |
1340 | * hardware cannot be accessed at this moment. So move all | 1353 | * hardware cannot be accessed at this moment. So move all |
1341 | * the mode_set config to ->enable() hook. | 1354 | * the mode_set config to ->enable() hook. |
1342 | * And this hook is called only when 'mode_changed' is true, | 1355 | * And this hook is called only when 'mode_changed' is true, |
1343 | * so it is called not every time atomic commit. | 1356 | * so it is called not every time atomic commit. |
1344 | */ | 1357 | */ |
1345 | 1358 | ||
1346 | /* workaround for CEA standard mode "1280x720@60" | 1359 | /* workaround for CEA standard mode "1280x720@60" |
1347 | * display on 4 data lanes with Non-burst with sync | 1360 | * display on 4 data lanes with Non-burst with sync |
1348 | * pulse DSI mode, since use the standard horizontal | 1361 | * pulse DSI mode, since use the standard horizontal |
1349 | * timings cannot display correctly. And this code | 1362 | * timings cannot display correctly. And this code |
1350 | * cannot be put into the dsim Bridge's mode_fixup, | 1363 | * cannot be put into the dsim Bridge's mode_fixup, |
1351 | * since the DSI device lane number change always | 1364 | * since the DSI device lane number change always |
1352 | * happens after that. | 1365 | * happens after that. |
1353 | */ | 1366 | */ |
1354 | if (!strcmp(mode->name, "1280x720") && | 1367 | if (!strcmp(mode->name, "1280x720") && |
1355 | mode->vrefresh == 60 && | 1368 | mode->vrefresh == 60 && |
1356 | dsim->lanes == 4 && | 1369 | dsim->lanes == 4 && |
1357 | dsim->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { | 1370 | dsim->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { |
1358 | adjusted_mode->hsync_start += 2; | 1371 | adjusted_mode->hsync_start += 2; |
1359 | adjusted_mode->hsync_end += 2; | 1372 | adjusted_mode->hsync_end += 2; |
1360 | adjusted_mode->htotal += 2; | 1373 | adjusted_mode->htotal += 2; |
1361 | } | 1374 | } |
1362 | 1375 | ||
1363 | drm_display_mode_to_videomode(adjusted_mode, &dsim->vmode); | 1376 | drm_display_mode_to_videomode(adjusted_mode, &dsim->vmode); |
1364 | } | 1377 | } |
1365 | 1378 | ||
1366 | static const struct drm_bridge_funcs sec_mipi_dsim_bridge_funcs = { | 1379 | static const struct drm_bridge_funcs sec_mipi_dsim_bridge_funcs = { |
1367 | .attach = sec_mipi_dsim_bridge_attach, | 1380 | .attach = sec_mipi_dsim_bridge_attach, |
1368 | .enable = sec_mipi_dsim_bridge_enable, | 1381 | .enable = sec_mipi_dsim_bridge_enable, |
1369 | .disable = sec_mipi_dsim_bridge_disable, | 1382 | .disable = sec_mipi_dsim_bridge_disable, |
1370 | .mode_set = sec_mipi_dsim_bridge_mode_set, | 1383 | .mode_set = sec_mipi_dsim_bridge_mode_set, |
1371 | .mode_fixup = sec_mipi_dsim_bridge_mode_fixup, | 1384 | .mode_fixup = sec_mipi_dsim_bridge_mode_fixup, |
1372 | }; | 1385 | }; |
1373 | 1386 | ||
1374 | void sec_mipi_dsim_suspend(struct device *dev) | 1387 | void sec_mipi_dsim_suspend(struct device *dev) |
1375 | { | 1388 | { |
1376 | struct sec_mipi_dsim *dsim = dev_get_drvdata(dev); | 1389 | struct sec_mipi_dsim *dsim = dev_get_drvdata(dev); |
1377 | 1390 | ||
1378 | /* TODO: add dsim reset */ | 1391 | /* TODO: add dsim reset */ |
1379 | 1392 | ||
1380 | clk_disable_unprepare(dsim->clk_cfg); | 1393 | clk_disable_unprepare(dsim->clk_cfg); |
1381 | 1394 | ||
1382 | clk_disable_unprepare(dsim->clk_pllref); | 1395 | clk_disable_unprepare(dsim->clk_pllref); |
1383 | } | 1396 | } |
1384 | EXPORT_SYMBOL(sec_mipi_dsim_suspend); | 1397 | EXPORT_SYMBOL(sec_mipi_dsim_suspend); |
1385 | 1398 | ||
1386 | void sec_mipi_dsim_resume(struct device *dev) | 1399 | void sec_mipi_dsim_resume(struct device *dev) |
1387 | { | 1400 | { |
1388 | struct sec_mipi_dsim *dsim = dev_get_drvdata(dev); | 1401 | struct sec_mipi_dsim *dsim = dev_get_drvdata(dev); |
1389 | 1402 | ||
1390 | clk_prepare_enable(dsim->clk_pllref); | 1403 | clk_prepare_enable(dsim->clk_pllref); |
1391 | 1404 | ||
1392 | clk_prepare_enable(dsim->clk_cfg); | 1405 | clk_prepare_enable(dsim->clk_cfg); |
1393 | 1406 | ||
1394 | sec_mipi_dsim_irq_init(dsim); | 1407 | sec_mipi_dsim_irq_init(dsim); |
1395 | 1408 | ||
1396 | /* TODO: add dsim de-reset */ | 1409 | /* TODO: add dsim de-reset */ |
1397 | } | 1410 | } |
1398 | EXPORT_SYMBOL(sec_mipi_dsim_resume); | 1411 | EXPORT_SYMBOL(sec_mipi_dsim_resume); |
1399 | 1412 | ||
1400 | static void __maybe_unused sec_mipi_dsim_irq_mask(struct sec_mipi_dsim *dsim, | 1413 | static void __maybe_unused sec_mipi_dsim_irq_mask(struct sec_mipi_dsim *dsim, |
1401 | int irq_idx) | 1414 | int irq_idx) |
1402 | { | 1415 | { |
1403 | uint32_t intmsk; | 1416 | uint32_t intmsk; |
1404 | 1417 | ||
1405 | intmsk = dsim_read(dsim, DSIM_INTMSK); | 1418 | intmsk = dsim_read(dsim, DSIM_INTMSK); |
1406 | 1419 | ||
1407 | switch (irq_idx) { | 1420 | switch (irq_idx) { |
1408 | case PLLSTABLE: | 1421 | case PLLSTABLE: |
1409 | intmsk |= INTMSK_MSKPLLSTABLE; | 1422 | intmsk |= INTMSK_MSKPLLSTABLE; |
1410 | break; | 1423 | break; |
1411 | case SWRSTRELEASE: | 1424 | case SWRSTRELEASE: |
1412 | intmsk |= INTMSK_MSKSWRELEASE; | 1425 | intmsk |= INTMSK_MSKSWRELEASE; |
1413 | break; | 1426 | break; |
1414 | case SFRPLFIFOEMPTY: | 1427 | case SFRPLFIFOEMPTY: |
1415 | intmsk |= INTMSK_MSKSFRPLFIFOEMPTY; | 1428 | intmsk |= INTMSK_MSKSFRPLFIFOEMPTY; |
1416 | break; | 1429 | break; |
1417 | case SFRPHFIFOEMPTY: | 1430 | case SFRPHFIFOEMPTY: |
1418 | intmsk |= INTMSK_MSKSFRPHFIFOEMPTY; | 1431 | intmsk |= INTMSK_MSKSFRPHFIFOEMPTY; |
1419 | break; | 1432 | break; |
1420 | case FRAMEDONE: | 1433 | case FRAMEDONE: |
1421 | intmsk |= INTMSK_MSKFRAMEDONE; | 1434 | intmsk |= INTMSK_MSKFRAMEDONE; |
1422 | break; | 1435 | break; |
1423 | case LPDRTOUT: | 1436 | case LPDRTOUT: |
1424 | intmsk |= INTMSK_MSKLPDRTOUT; | 1437 | intmsk |= INTMSK_MSKLPDRTOUT; |
1425 | break; | 1438 | break; |
1426 | case TATOUT: | 1439 | case TATOUT: |
1427 | intmsk |= INTMSK_MSKTATOUT; | 1440 | intmsk |= INTMSK_MSKTATOUT; |
1428 | break; | 1441 | break; |
1429 | case RXDATDONE: | 1442 | case RXDATDONE: |
1430 | intmsk |= INTMSK_MSKRXDATDONE; | 1443 | intmsk |= INTMSK_MSKRXDATDONE; |
1431 | break; | 1444 | break; |
1432 | case RXTE: | 1445 | case RXTE: |
1433 | intmsk |= INTMSK_MSKRXTE; | 1446 | intmsk |= INTMSK_MSKRXTE; |
1434 | break; | 1447 | break; |
1435 | case RXACK: | 1448 | case RXACK: |
1436 | intmsk |= INTMSK_MSKRXACK; | 1449 | intmsk |= INTMSK_MSKRXACK; |
1437 | break; | 1450 | break; |
1438 | default: | 1451 | default: |
1439 | /* unsupported irq */ | 1452 | /* unsupported irq */ |
1440 | return; | 1453 | return; |
1441 | } | 1454 | } |
1442 | 1455 | ||
1443 | writel(intmsk, dsim->base + DSIM_INTMSK); | 1456 | writel(intmsk, dsim->base + DSIM_INTMSK); |
1444 | } | 1457 | } |
1445 | 1458 | ||
1446 | static void sec_mipi_dsim_irq_unmask(struct sec_mipi_dsim *dsim, | 1459 | static void sec_mipi_dsim_irq_unmask(struct sec_mipi_dsim *dsim, |
1447 | int irq_idx) | 1460 | int irq_idx) |
1448 | { | 1461 | { |
1449 | uint32_t intmsk; | 1462 | uint32_t intmsk; |
1450 | 1463 | ||
1451 | intmsk = dsim_read(dsim, DSIM_INTMSK); | 1464 | intmsk = dsim_read(dsim, DSIM_INTMSK); |
1452 | 1465 | ||
1453 | switch (irq_idx) { | 1466 | switch (irq_idx) { |
1454 | case PLLSTABLE: | 1467 | case PLLSTABLE: |
1455 | intmsk &= ~INTMSK_MSKPLLSTABLE; | 1468 | intmsk &= ~INTMSK_MSKPLLSTABLE; |
1456 | break; | 1469 | break; |
1457 | case SWRSTRELEASE: | 1470 | case SWRSTRELEASE: |
1458 | intmsk &= ~INTMSK_MSKSWRELEASE; | 1471 | intmsk &= ~INTMSK_MSKSWRELEASE; |
1459 | break; | 1472 | break; |
1460 | case SFRPLFIFOEMPTY: | 1473 | case SFRPLFIFOEMPTY: |
1461 | intmsk &= ~INTMSK_MSKSFRPLFIFOEMPTY; | 1474 | intmsk &= ~INTMSK_MSKSFRPLFIFOEMPTY; |
1462 | break; | 1475 | break; |
1463 | case SFRPHFIFOEMPTY: | 1476 | case SFRPHFIFOEMPTY: |
1464 | intmsk &= ~INTMSK_MSKSFRPHFIFOEMPTY; | 1477 | intmsk &= ~INTMSK_MSKSFRPHFIFOEMPTY; |
1465 | break; | 1478 | break; |
1466 | case FRAMEDONE: | 1479 | case FRAMEDONE: |
1467 | intmsk &= ~INTMSK_MSKFRAMEDONE; | 1480 | intmsk &= ~INTMSK_MSKFRAMEDONE; |
1468 | break; | 1481 | break; |
1469 | case LPDRTOUT: | 1482 | case LPDRTOUT: |
1470 | intmsk &= ~INTMSK_MSKLPDRTOUT; | 1483 | intmsk &= ~INTMSK_MSKLPDRTOUT; |
1471 | break; | 1484 | break; |
1472 | case TATOUT: | 1485 | case TATOUT: |
1473 | intmsk &= ~INTMSK_MSKTATOUT; | 1486 | intmsk &= ~INTMSK_MSKTATOUT; |
1474 | break; | 1487 | break; |
1475 | case RXDATDONE: | 1488 | case RXDATDONE: |
1476 | intmsk &= ~INTMSK_MSKRXDATDONE; | 1489 | intmsk &= ~INTMSK_MSKRXDATDONE; |
1477 | break; | 1490 | break; |
1478 | case RXTE: | 1491 | case RXTE: |
1479 | intmsk &= ~INTMSK_MSKRXTE; | 1492 | intmsk &= ~INTMSK_MSKRXTE; |
1480 | break; | 1493 | break; |
1481 | case RXACK: | 1494 | case RXACK: |
1482 | intmsk &= ~INTMSK_MSKRXACK; | 1495 | intmsk &= ~INTMSK_MSKRXACK; |
1483 | break; | 1496 | break; |
1484 | default: | 1497 | default: |
1485 | /* unsupported irq */ | 1498 | /* unsupported irq */ |
1486 | return; | 1499 | return; |
1487 | } | 1500 | } |
1488 | 1501 | ||
1489 | dsim_write(dsim, intmsk, DSIM_INTMSK); | 1502 | dsim_write(dsim, intmsk, DSIM_INTMSK); |
1490 | } | 1503 | } |
1491 | 1504 | ||
1492 | /* write 1 clear irq */ | 1505 | /* write 1 clear irq */ |
1493 | static void sec_mipi_dsim_irq_clear(struct sec_mipi_dsim *dsim, | 1506 | static void sec_mipi_dsim_irq_clear(struct sec_mipi_dsim *dsim, |
1494 | int irq_idx) | 1507 | int irq_idx) |
1495 | { | 1508 | { |
1496 | uint32_t intsrc = 0; | 1509 | uint32_t intsrc = 0; |
1497 | 1510 | ||
1498 | switch (irq_idx) { | 1511 | switch (irq_idx) { |
1499 | case PLLSTABLE: | 1512 | case PLLSTABLE: |
1500 | intsrc |= INTSRC_PLLSTABLE; | 1513 | intsrc |= INTSRC_PLLSTABLE; |
1501 | break; | 1514 | break; |
1502 | case SWRSTRELEASE: | 1515 | case SWRSTRELEASE: |
1503 | intsrc |= INTSRC_SWRSTRELEASE; | 1516 | intsrc |= INTSRC_SWRSTRELEASE; |
1504 | break; | 1517 | break; |
1505 | case SFRPLFIFOEMPTY: | 1518 | case SFRPLFIFOEMPTY: |
1506 | intsrc |= INTSRC_SFRPLFIFOEMPTY; | 1519 | intsrc |= INTSRC_SFRPLFIFOEMPTY; |
1507 | break; | 1520 | break; |
1508 | case SFRPHFIFOEMPTY: | 1521 | case SFRPHFIFOEMPTY: |
1509 | intsrc |= INTSRC_SFRPHFIFOEMPTY; | 1522 | intsrc |= INTSRC_SFRPHFIFOEMPTY; |
1510 | break; | 1523 | break; |
1511 | case FRAMEDONE: | 1524 | case FRAMEDONE: |
1512 | intsrc |= INTSRC_FRAMEDONE; | 1525 | intsrc |= INTSRC_FRAMEDONE; |
1513 | break; | 1526 | break; |
1514 | case LPDRTOUT: | 1527 | case LPDRTOUT: |
1515 | intsrc |= INTSRC_LPDRTOUT; | 1528 | intsrc |= INTSRC_LPDRTOUT; |
1516 | break; | 1529 | break; |
1517 | case TATOUT: | 1530 | case TATOUT: |
1518 | intsrc |= INTSRC_TATOUT; | 1531 | intsrc |= INTSRC_TATOUT; |
1519 | break; | 1532 | break; |
1520 | case RXDATDONE: | 1533 | case RXDATDONE: |
1521 | intsrc |= INTSRC_RXDATDONE; | 1534 | intsrc |= INTSRC_RXDATDONE; |
1522 | break; | 1535 | break; |
1523 | case RXTE: | 1536 | case RXTE: |
1524 | intsrc |= INTSRC_RXTE; | 1537 | intsrc |= INTSRC_RXTE; |
1525 | break; | 1538 | break; |
1526 | case RXACK: | 1539 | case RXACK: |
1527 | intsrc |= INTSRC_RXACK; | 1540 | intsrc |= INTSRC_RXACK; |
1528 | break; | 1541 | break; |
1529 | default: | 1542 | default: |
1530 | /* unsupported irq */ | 1543 | /* unsupported irq */ |
1531 | return; | 1544 | return; |
1532 | } | 1545 | } |
1533 | 1546 | ||
1534 | dsim_write(dsim, intsrc, DSIM_INTSRC); | 1547 | dsim_write(dsim, intsrc, DSIM_INTSRC); |
1535 | } | 1548 | } |
1536 | 1549 | ||
1537 | static void sec_mipi_dsim_irq_init(struct sec_mipi_dsim *dsim) | 1550 | static void sec_mipi_dsim_irq_init(struct sec_mipi_dsim *dsim) |
1538 | { | 1551 | { |
1539 | sec_mipi_dsim_irq_unmask(dsim, PLLSTABLE); | 1552 | sec_mipi_dsim_irq_unmask(dsim, PLLSTABLE); |
1540 | sec_mipi_dsim_irq_unmask(dsim, SWRSTRELEASE); | 1553 | sec_mipi_dsim_irq_unmask(dsim, SWRSTRELEASE); |
1541 | 1554 | ||
1542 | if (dsim->panel) { | 1555 | if (dsim->panel) { |
1543 | sec_mipi_dsim_irq_unmask(dsim, SFRPLFIFOEMPTY); | 1556 | sec_mipi_dsim_irq_unmask(dsim, SFRPLFIFOEMPTY); |
1544 | sec_mipi_dsim_irq_unmask(dsim, SFRPHFIFOEMPTY); | 1557 | sec_mipi_dsim_irq_unmask(dsim, SFRPHFIFOEMPTY); |
1545 | sec_mipi_dsim_irq_unmask(dsim, LPDRTOUT); | 1558 | sec_mipi_dsim_irq_unmask(dsim, LPDRTOUT); |
1546 | sec_mipi_dsim_irq_unmask(dsim, TATOUT); | 1559 | sec_mipi_dsim_irq_unmask(dsim, TATOUT); |
1547 | sec_mipi_dsim_irq_unmask(dsim, RXDATDONE); | 1560 | sec_mipi_dsim_irq_unmask(dsim, RXDATDONE); |
1548 | sec_mipi_dsim_irq_unmask(dsim, RXTE); | 1561 | sec_mipi_dsim_irq_unmask(dsim, RXTE); |
1549 | sec_mipi_dsim_irq_unmask(dsim, RXACK); | 1562 | sec_mipi_dsim_irq_unmask(dsim, RXACK); |
1550 | } | 1563 | } |
1551 | } | 1564 | } |
1552 | 1565 | ||
1553 | static irqreturn_t sec_mipi_dsim_irq_handler(int irq, void *data) | 1566 | static irqreturn_t sec_mipi_dsim_irq_handler(int irq, void *data) |
1554 | { | 1567 | { |
1555 | uint32_t intsrc, status; | 1568 | uint32_t intsrc, status; |
1556 | struct sec_mipi_dsim *dsim = data; | 1569 | struct sec_mipi_dsim *dsim = data; |
1557 | 1570 | ||
1558 | intsrc = dsim_read(dsim, DSIM_INTSRC); | 1571 | intsrc = dsim_read(dsim, DSIM_INTSRC); |
1559 | status = dsim_read(dsim, DSIM_STATUS); | 1572 | status = dsim_read(dsim, DSIM_STATUS); |
1560 | 1573 | ||
1561 | if (WARN_ON(!intsrc)) { | 1574 | if (WARN_ON(!intsrc)) { |
1562 | dev_err(dsim->dev, "interrupt is not from dsim\n"); | 1575 | dev_err(dsim->dev, "interrupt is not from dsim\n"); |
1563 | return IRQ_NONE; | 1576 | return IRQ_NONE; |
1564 | } | 1577 | } |
1565 | 1578 | ||
1566 | if (WARN_ON(!(intsrc & INTSRC_MASK))) { | 1579 | if (WARN_ON(!(intsrc & INTSRC_MASK))) { |
1567 | dev_warn(dsim->dev, "unenable irq happens: %#x\n", intsrc); | 1580 | dev_warn(dsim->dev, "unenable irq happens: %#x\n", intsrc); |
1568 | /* just clear irqs */ | 1581 | /* just clear irqs */ |
1569 | dsim_write(dsim, intsrc, DSIM_INTSRC); | 1582 | dsim_write(dsim, intsrc, DSIM_INTSRC); |
1570 | return IRQ_NONE; | 1583 | return IRQ_NONE; |
1571 | } | 1584 | } |
1572 | 1585 | ||
1573 | if (intsrc & INTSRC_PLLSTABLE) { | 1586 | if (intsrc & INTSRC_PLLSTABLE) { |
1574 | WARN_ON(!(status & STATUS_PLLSTABLE)); | 1587 | WARN_ON(!(status & STATUS_PLLSTABLE)); |
1575 | sec_mipi_dsim_irq_clear(dsim, PLLSTABLE); | 1588 | sec_mipi_dsim_irq_clear(dsim, PLLSTABLE); |
1576 | complete(&dsim->pll_stable); | 1589 | complete(&dsim->pll_stable); |
1577 | } | 1590 | } |
1578 | 1591 | ||
1579 | if (intsrc & INTSRC_SWRSTRELEASE) | 1592 | if (intsrc & INTSRC_SWRSTRELEASE) |
1580 | sec_mipi_dsim_irq_clear(dsim, SWRSTRELEASE); | 1593 | sec_mipi_dsim_irq_clear(dsim, SWRSTRELEASE); |
1581 | 1594 | ||
1582 | if (intsrc & INTSRC_SFRPLFIFOEMPTY) { | 1595 | if (intsrc & INTSRC_SFRPLFIFOEMPTY) { |
1583 | sec_mipi_dsim_irq_clear(dsim, SFRPLFIFOEMPTY); | 1596 | sec_mipi_dsim_irq_clear(dsim, SFRPLFIFOEMPTY); |
1584 | complete(&dsim->pl_tx_done); | 1597 | complete(&dsim->pl_tx_done); |
1585 | } | 1598 | } |
1586 | 1599 | ||
1587 | if (intsrc & INTSRC_SFRPHFIFOEMPTY) { | 1600 | if (intsrc & INTSRC_SFRPHFIFOEMPTY) { |
1588 | sec_mipi_dsim_irq_clear(dsim, SFRPHFIFOEMPTY); | 1601 | sec_mipi_dsim_irq_clear(dsim, SFRPHFIFOEMPTY); |
1589 | complete(&dsim->ph_tx_done); | 1602 | complete(&dsim->ph_tx_done); |
1590 | } | 1603 | } |
1591 | 1604 | ||
1592 | if (WARN_ON(intsrc & INTSRC_LPDRTOUT)) { | 1605 | if (WARN_ON(intsrc & INTSRC_LPDRTOUT)) { |
1593 | sec_mipi_dsim_irq_clear(dsim, LPDRTOUT); | 1606 | sec_mipi_dsim_irq_clear(dsim, LPDRTOUT); |
1594 | dev_warn(dsim->dev, "LP RX timeout\n"); | 1607 | dev_warn(dsim->dev, "LP RX timeout\n"); |
1595 | } | 1608 | } |
1596 | 1609 | ||
1597 | if (WARN_ON(intsrc & INTSRC_TATOUT)) { | 1610 | if (WARN_ON(intsrc & INTSRC_TATOUT)) { |
1598 | sec_mipi_dsim_irq_clear(dsim, TATOUT); | 1611 | sec_mipi_dsim_irq_clear(dsim, TATOUT); |
1599 | dev_warn(dsim->dev, "Turns around Acknowledge timeout\n"); | 1612 | dev_warn(dsim->dev, "Turns around Acknowledge timeout\n"); |
1600 | } | 1613 | } |
1601 | 1614 | ||
1602 | if (intsrc & INTSRC_RXDATDONE) { | 1615 | if (intsrc & INTSRC_RXDATDONE) { |
1603 | sec_mipi_dsim_irq_clear(dsim, RXDATDONE); | 1616 | sec_mipi_dsim_irq_clear(dsim, RXDATDONE); |
1604 | complete(&dsim->rx_done); | 1617 | complete(&dsim->rx_done); |
1605 | } | 1618 | } |
1606 | 1619 | ||
1607 | if (intsrc & INTSRC_RXTE) { | 1620 | if (intsrc & INTSRC_RXTE) { |
1608 | sec_mipi_dsim_irq_clear(dsim, RXTE); | 1621 | sec_mipi_dsim_irq_clear(dsim, RXTE); |
1609 | dev_dbg(dsim->dev, "TE Rx trigger received\n"); | 1622 | dev_dbg(dsim->dev, "TE Rx trigger received\n"); |
1610 | } | 1623 | } |
1611 | 1624 | ||
1612 | if (intsrc & INTSRC_RXACK) { | 1625 | if (intsrc & INTSRC_RXACK) { |
1613 | sec_mipi_dsim_irq_clear(dsim, RXACK); | 1626 | sec_mipi_dsim_irq_clear(dsim, RXACK); |
1614 | dev_dbg(dsim->dev, "ACK Rx trigger received\n"); | 1627 | dev_dbg(dsim->dev, "ACK Rx trigger received\n"); |
1615 | } | 1628 | } |
1616 | 1629 | ||
1617 | return IRQ_HANDLED; | 1630 | return IRQ_HANDLED; |
1618 | } | 1631 | } |
1619 | 1632 | ||
1620 | static int sec_mipi_dsim_connector_get_modes(struct drm_connector *connector) | 1633 | static int sec_mipi_dsim_connector_get_modes(struct drm_connector *connector) |
1621 | { | 1634 | { |
1622 | struct sec_mipi_dsim *dsim = conn_to_sec_mipi_dsim(connector); | 1635 | struct sec_mipi_dsim *dsim = conn_to_sec_mipi_dsim(connector); |
1623 | 1636 | ||
1624 | if (WARN_ON(!dsim->panel)) | 1637 | if (WARN_ON(!dsim->panel)) |
1625 | return -ENODEV; | 1638 | return -ENODEV; |
1626 | 1639 | ||
1627 | return drm_panel_get_modes(dsim->panel); | 1640 | return drm_panel_get_modes(dsim->panel); |
1628 | } | 1641 | } |
1629 | 1642 | ||
1630 | static const struct drm_connector_helper_funcs | 1643 | static const struct drm_connector_helper_funcs |
1631 | sec_mipi_dsim_connector_helper_funcs = { | 1644 | sec_mipi_dsim_connector_helper_funcs = { |
1632 | .get_modes = sec_mipi_dsim_connector_get_modes, | 1645 | .get_modes = sec_mipi_dsim_connector_get_modes, |
1633 | }; | 1646 | }; |
1634 | 1647 | ||
1635 | static enum drm_connector_status | 1648 | static enum drm_connector_status |
1636 | sec_mipi_dsim_connector_detect(struct drm_connector *connector, | 1649 | sec_mipi_dsim_connector_detect(struct drm_connector *connector, |
1637 | bool force) | 1650 | bool force) |
1638 | { | 1651 | { |
1639 | /* TODO: add support later */ | 1652 | /* TODO: add support later */ |
1640 | 1653 | ||
1641 | return connector_status_connected; | 1654 | return connector_status_connected; |
1642 | } | 1655 | } |
1643 | 1656 | ||
1644 | static const struct drm_connector_funcs sec_mipi_dsim_connector_funcs = { | 1657 | static const struct drm_connector_funcs sec_mipi_dsim_connector_funcs = { |
1645 | .detect = sec_mipi_dsim_connector_detect, | 1658 | .detect = sec_mipi_dsim_connector_detect, |
1646 | .fill_modes = drm_helper_probe_single_connector_modes, | 1659 | .fill_modes = drm_helper_probe_single_connector_modes, |
1647 | .destroy = drm_connector_cleanup, | 1660 | .destroy = drm_connector_cleanup, |
1648 | .reset = drm_atomic_helper_connector_reset, | 1661 | .reset = drm_atomic_helper_connector_reset, |
1649 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, | 1662 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, |
1650 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, | 1663 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
1651 | }; | 1664 | }; |
1652 | 1665 | ||
1653 | int sec_mipi_dsim_bind(struct device *dev, struct device *master, void *data, | 1666 | int sec_mipi_dsim_bind(struct device *dev, struct device *master, void *data, |
1654 | struct drm_encoder *encoder, struct resource *res, | 1667 | struct drm_encoder *encoder, struct resource *res, |
1655 | int irq, const struct sec_mipi_dsim_plat_data *pdata) | 1668 | int irq, const struct sec_mipi_dsim_plat_data *pdata) |
1656 | { | 1669 | { |
1657 | int ret, version; | 1670 | int ret, version; |
1658 | struct drm_device *drm_dev = data; | 1671 | struct drm_device *drm_dev = data; |
1659 | struct drm_bridge *bridge; | 1672 | struct drm_bridge *bridge; |
1660 | struct drm_connector *connector; | 1673 | struct drm_connector *connector; |
1661 | struct sec_mipi_dsim *dsim; | 1674 | struct sec_mipi_dsim *dsim; |
1662 | 1675 | ||
1663 | dev_dbg(dev, "sec-dsim bridge bind begin\n"); | 1676 | dev_dbg(dev, "sec-dsim bridge bind begin\n"); |
1664 | 1677 | ||
1665 | dsim = devm_kzalloc(dev, sizeof(*dsim), GFP_KERNEL); | 1678 | dsim = devm_kzalloc(dev, sizeof(*dsim), GFP_KERNEL); |
1666 | if (!dsim) { | 1679 | if (!dsim) { |
1667 | dev_err(dev, "Unable to allocate 'dsim'\n"); | 1680 | dev_err(dev, "Unable to allocate 'dsim'\n"); |
1668 | return -ENOMEM; | 1681 | return -ENOMEM; |
1669 | } | 1682 | } |
1670 | 1683 | ||
1671 | dsim->dev = dev; | 1684 | dsim->dev = dev; |
1672 | dsim->irq = irq; | 1685 | dsim->irq = irq; |
1673 | dsim->pdata = pdata; | 1686 | dsim->pdata = pdata; |
1674 | dsim->encoder = encoder; | 1687 | dsim->encoder = encoder; |
1675 | 1688 | ||
1676 | dsim->dsi_host.ops = &sec_mipi_dsim_host_ops; | 1689 | dsim->dsi_host.ops = &sec_mipi_dsim_host_ops; |
1677 | dsim->dsi_host.dev = dev; | 1690 | dsim->dsi_host.dev = dev; |
1678 | 1691 | ||
1679 | dsim->base = devm_ioremap_resource(dev, res); | 1692 | dsim->base = devm_ioremap_resource(dev, res); |
1680 | if (IS_ERR(dsim->base)) | 1693 | if (IS_ERR(dsim->base)) |
1681 | return PTR_ERR(dsim->base); | 1694 | return PTR_ERR(dsim->base); |
1682 | 1695 | ||
1683 | dsim->clk_pllref = devm_clk_get(dev, "pll-ref"); | 1696 | dsim->clk_pllref = devm_clk_get(dev, "pll-ref"); |
1684 | if (IS_ERR(dsim->clk_pllref)) { | 1697 | if (IS_ERR(dsim->clk_pllref)) { |
1685 | ret = PTR_ERR(dsim->clk_pllref); | 1698 | ret = PTR_ERR(dsim->clk_pllref); |
1686 | dev_err(dev, "Unable to get phy pll reference clock: %d\n", ret); | 1699 | dev_err(dev, "Unable to get phy pll reference clock: %d\n", ret); |
1687 | return ret; | 1700 | return ret; |
1688 | } | 1701 | } |
1689 | 1702 | ||
1690 | dsim->clk_cfg = devm_clk_get(dev, "cfg"); | 1703 | dsim->clk_cfg = devm_clk_get(dev, "cfg"); |
1691 | if (IS_ERR(dsim->clk_cfg)) { | 1704 | if (IS_ERR(dsim->clk_cfg)) { |
1692 | ret = PTR_ERR(dsim->clk_cfg); | 1705 | ret = PTR_ERR(dsim->clk_cfg); |
1693 | dev_err(dev, "Unable to get configuration clock: %d\n", ret); | 1706 | dev_err(dev, "Unable to get configuration clock: %d\n", ret); |
1694 | return ret; | 1707 | return ret; |
1695 | } | 1708 | } |
1696 | 1709 | ||
1697 | clk_prepare_enable(dsim->clk_cfg); | 1710 | clk_prepare_enable(dsim->clk_cfg); |
1698 | version = dsim_read(dsim, DSIM_VERSION); | 1711 | version = dsim_read(dsim, DSIM_VERSION); |
1699 | WARN_ON(version != pdata->version); | 1712 | WARN_ON(version != pdata->version); |
1700 | clk_disable_unprepare(dsim->clk_cfg); | 1713 | clk_disable_unprepare(dsim->clk_cfg); |
1701 | 1714 | ||
1702 | dev_info(dev, "version number is %#x\n", version); | 1715 | dev_info(dev, "version number is %#x\n", version); |
1703 | 1716 | ||
1704 | /* TODO: set pll ref clock rate to be fixed with 27MHz */ | 1717 | /* TODO: set pll ref clock rate to be fixed with 27MHz */ |
1705 | ret = clk_set_rate(dsim->clk_pllref, PHY_REF_CLK); | 1718 | ret = clk_set_rate(dsim->clk_pllref, PHY_REF_CLK); |
1706 | if (ret) { | 1719 | if (ret) { |
1707 | dev_err(dev, "failed to set pll ref clock rate\n"); | 1720 | dev_err(dev, "failed to set pll ref clock rate\n"); |
1708 | return ret; | 1721 | return ret; |
1709 | } | 1722 | } |
1710 | 1723 | ||
1711 | ret = devm_request_irq(dev, dsim->irq, | 1724 | ret = devm_request_irq(dev, dsim->irq, |
1712 | sec_mipi_dsim_irq_handler, | 1725 | sec_mipi_dsim_irq_handler, |
1713 | 0, dev_name(dev), dsim); | 1726 | 0, dev_name(dev), dsim); |
1714 | if (ret) { | 1727 | if (ret) { |
1715 | dev_err(dev, "failed to request dsim irq: %d\n", ret); | 1728 | dev_err(dev, "failed to request dsim irq: %d\n", ret); |
1716 | return ret; | 1729 | return ret; |
1717 | } | 1730 | } |
1718 | 1731 | ||
1719 | init_completion(&dsim->pll_stable); | 1732 | init_completion(&dsim->pll_stable); |
1720 | init_completion(&dsim->ph_tx_done); | 1733 | init_completion(&dsim->ph_tx_done); |
1721 | init_completion(&dsim->pl_tx_done); | 1734 | init_completion(&dsim->pl_tx_done); |
1722 | init_completion(&dsim->rx_done); | 1735 | init_completion(&dsim->rx_done); |
1723 | 1736 | ||
1724 | /* Initialize and attach sec dsim bridge */ | 1737 | /* Initialize and attach sec dsim bridge */ |
1725 | bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL); | 1738 | bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL); |
1726 | if (!bridge) { | 1739 | if (!bridge) { |
1727 | dev_err(dev, "Unable to allocate 'bridge'\n"); | 1740 | dev_err(dev, "Unable to allocate 'bridge'\n"); |
1728 | return -ENOMEM; | 1741 | return -ENOMEM; |
1729 | } | 1742 | } |
1730 | 1743 | ||
1731 | /* mipi dsi host needs to be registered before bridge attach, since: | 1744 | /* mipi dsi host needs to be registered before bridge attach, since: |
1732 | * 1. Have Panel | 1745 | * 1. Have Panel |
1733 | * The 'mipi_dsi_host_register' will allocate a mipi_dsi_device | 1746 | * The 'mipi_dsi_host_register' will allocate a mipi_dsi_device |
1734 | * if the dsi host node has a panel child node in DTB. And dsi | 1747 | * if the dsi host node has a panel child node in DTB. And dsi |
1735 | * host ->attach() will be called in panel's probe(). | 1748 | * host ->attach() will be called in panel's probe(). |
1736 | * | 1749 | * |
1737 | * 2. Have Bridge | 1750 | * 2. Have Bridge |
1738 | * The dsi host ->attach() will be called through the below | 1751 | * The dsi host ->attach() will be called through the below |
1739 | * 'drm_bridge_attach()' which will attach next bridge in a | 1752 | * 'drm_bridge_attach()' which will attach next bridge in a |
1740 | * chain. | 1753 | * chain. |
1741 | */ | 1754 | */ |
1742 | ret = mipi_dsi_host_register(&dsim->dsi_host); | 1755 | ret = mipi_dsi_host_register(&dsim->dsi_host); |
1743 | if (ret) { | 1756 | if (ret) { |
1744 | dev_err(dev, "Unable to register mipi dsi host: %d\n", ret); | 1757 | dev_err(dev, "Unable to register mipi dsi host: %d\n", ret); |
1745 | return ret; | 1758 | return ret; |
1746 | } | 1759 | } |
1747 | 1760 | ||
1748 | dsim->bridge = bridge; | 1761 | dsim->bridge = bridge; |
1749 | bridge->driver_private = dsim; | 1762 | bridge->driver_private = dsim; |
1750 | bridge->funcs = &sec_mipi_dsim_bridge_funcs; | 1763 | bridge->funcs = &sec_mipi_dsim_bridge_funcs; |
1751 | bridge->of_node = dev->of_node; | 1764 | bridge->of_node = dev->of_node; |
1752 | bridge->encoder = encoder; | 1765 | bridge->encoder = encoder; |
1753 | encoder->bridge = bridge; | 1766 | encoder->bridge = bridge; |
1754 | 1767 | ||
1755 | dev_set_drvdata(dev, dsim); | 1768 | dev_set_drvdata(dev, dsim); |
1756 | 1769 | ||
1757 | /* attach sec dsim bridge and its next bridge if exists */ | 1770 | /* attach sec dsim bridge and its next bridge if exists */ |
1758 | ret = drm_bridge_attach(encoder, bridge, NULL); | 1771 | ret = drm_bridge_attach(encoder, bridge, NULL); |
1759 | if (ret) { | 1772 | if (ret) { |
1760 | dev_err(dev, "Failed to attach bridge: %s\n", dev_name(dev)); | 1773 | dev_err(dev, "Failed to attach bridge: %s\n", dev_name(dev)); |
1761 | mipi_dsi_host_unregister(&dsim->dsi_host); | 1774 | mipi_dsi_host_unregister(&dsim->dsi_host); |
1762 | return ret; | 1775 | return ret; |
1763 | } | 1776 | } |
1764 | 1777 | ||
1765 | if (dsim->panel) { | 1778 | if (dsim->panel) { |
1766 | /* A panel has been attached */ | 1779 | /* A panel has been attached */ |
1767 | connector = &dsim->connector; | 1780 | connector = &dsim->connector; |
1768 | 1781 | ||
1769 | drm_connector_helper_add(connector, | 1782 | drm_connector_helper_add(connector, |
1770 | &sec_mipi_dsim_connector_helper_funcs); | 1783 | &sec_mipi_dsim_connector_helper_funcs); |
1771 | ret = drm_connector_init(drm_dev, connector, | 1784 | ret = drm_connector_init(drm_dev, connector, |
1772 | &sec_mipi_dsim_connector_funcs, | 1785 | &sec_mipi_dsim_connector_funcs, |
1773 | DRM_MODE_CONNECTOR_DSI); | 1786 | DRM_MODE_CONNECTOR_DSI); |
1774 | if (ret) | 1787 | if (ret) |
1775 | goto host_unregister; | 1788 | goto host_unregister; |
1776 | 1789 | ||
1777 | /* TODO */ | 1790 | /* TODO */ |
1778 | connector->dpms = DRM_MODE_DPMS_OFF; | 1791 | connector->dpms = DRM_MODE_DPMS_OFF; |
1779 | 1792 | ||
1780 | ret = drm_mode_connector_attach_encoder(connector, encoder); | 1793 | ret = drm_mode_connector_attach_encoder(connector, encoder); |
1781 | if (ret) | 1794 | if (ret) |
1782 | goto cleanup_connector; | 1795 | goto cleanup_connector; |
1783 | 1796 | ||
1784 | ret = drm_panel_attach(dsim->panel, connector); | 1797 | ret = drm_panel_attach(dsim->panel, connector); |
1785 | if (ret) | 1798 | if (ret) |
1786 | goto cleanup_connector; | 1799 | goto cleanup_connector; |
1787 | } | 1800 | } |
1788 | 1801 | ||
1789 | dev_dbg(dev, "sec-dsim bridge bind end\n"); | 1802 | dev_dbg(dev, "sec-dsim bridge bind end\n"); |
1790 | 1803 | ||
1791 | return 0; | 1804 | return 0; |
1792 | 1805 | ||
1793 | cleanup_connector: | 1806 | cleanup_connector: |
1794 | drm_connector_cleanup(connector); | 1807 | drm_connector_cleanup(connector); |
1795 | host_unregister: | 1808 | host_unregister: |
1796 | mipi_dsi_host_unregister(&dsim->dsi_host); | 1809 | mipi_dsi_host_unregister(&dsim->dsi_host); |
1797 | return ret; | 1810 | return ret; |
1798 | } | 1811 | } |
1799 | EXPORT_SYMBOL(sec_mipi_dsim_bind); | 1812 | EXPORT_SYMBOL(sec_mipi_dsim_bind); |
1800 | 1813 | ||
1801 | void sec_mipi_dsim_unbind(struct device *dev, struct device *master, void *data) | 1814 | void sec_mipi_dsim_unbind(struct device *dev, struct device *master, void *data) |
1802 | { | 1815 | { |
1803 | struct sec_mipi_dsim *dsim = dev_get_drvdata(dev); | 1816 | struct sec_mipi_dsim *dsim = dev_get_drvdata(dev); |
1804 | 1817 | ||
1805 | if (dsim->panel) { | 1818 | if (dsim->panel) { |
1806 | drm_panel_detach(dsim->panel); | 1819 | drm_panel_detach(dsim->panel); |
1807 | drm_connector_cleanup(&dsim->connector); | 1820 | drm_connector_cleanup(&dsim->connector); |
1808 | dsim->panel = NULL; | 1821 | dsim->panel = NULL; |
1809 | } | 1822 | } |
1810 | 1823 | ||
1811 | mipi_dsi_host_unregister(&dsim->dsi_host); | 1824 | mipi_dsi_host_unregister(&dsim->dsi_host); |
1812 | } | 1825 | } |
1813 | EXPORT_SYMBOL(sec_mipi_dsim_unbind); | 1826 | EXPORT_SYMBOL(sec_mipi_dsim_unbind); |
1814 | 1827 | ||
1815 | MODULE_DESCRIPTION("Samsung MIPI DSI Host Controller bridge driver"); | 1828 | MODULE_DESCRIPTION("Samsung MIPI DSI Host Controller bridge driver"); |
1816 | MODULE_AUTHOR("Fancy Fang <chen.fang@nxp.com>"); | 1829 | MODULE_AUTHOR("Fancy Fang <chen.fang@nxp.com>"); |
1817 | MODULE_LICENSE("GPL"); | 1830 | MODULE_LICENSE("GPL"); |
1818 | 1831 |