diff options
author | Jitao Shi <jitao.shi@mediatek.com> | 2016-11-15 22:20:54 -0500 |
---|---|---|
committer | CK Hu <ck.hu@mediatek.com> | 2016-11-24 01:53:14 -0500 |
commit | f6c872397028837c80685ee96c4011c62abe9a73 (patch) | |
tree | 47927838d25847c3dee50bb8c420d760c70a7373 | |
parent | 1ee6f347f81925fa8f3816e69ca1b49021f37850 (diff) |
drm/mediatek: fixed the calc method of data rate per lane
Tune dsi frame rate by pixel clock, dsi add some extra signal (i.e.
Tlpx, Ths-prepare, Ths-zero, Ths-trail,Ths-exit) when enter and exit LP
mode, those signals will cause h-time larger than normal and reduce FPS.
So need to multiply a coefficient to offset the extra signal's effect.
coefficient = ((htotal*bpp/lane_number)+Tlpx+Ths_prep+Ths_zero+
Ths_trail+Ths_exit)/(htotal*bpp/lane_number)
Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
-rw-r--r-- | drivers/gpu/drm/mediatek/mtk_dsi.c | 64 |
1 files changed, 48 insertions, 16 deletions
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 28b2044ed9f2..eaa5a2240c0c 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c | |||
@@ -86,7 +86,7 @@ | |||
86 | 86 | ||
87 | #define DSI_PHY_TIMECON0 0x110 | 87 | #define DSI_PHY_TIMECON0 0x110 |
88 | #define LPX (0xff << 0) | 88 | #define LPX (0xff << 0) |
89 | #define HS_PRPR (0xff << 8) | 89 | #define HS_PREP (0xff << 8) |
90 | #define HS_ZERO (0xff << 16) | 90 | #define HS_ZERO (0xff << 16) |
91 | #define HS_TRAIL (0xff << 24) | 91 | #define HS_TRAIL (0xff << 24) |
92 | 92 | ||
@@ -102,10 +102,16 @@ | |||
102 | #define CLK_TRAIL (0xff << 24) | 102 | #define CLK_TRAIL (0xff << 24) |
103 | 103 | ||
104 | #define DSI_PHY_TIMECON3 0x11c | 104 | #define DSI_PHY_TIMECON3 0x11c |
105 | #define CLK_HS_PRPR (0xff << 0) | 105 | #define CLK_HS_PREP (0xff << 0) |
106 | #define CLK_HS_POST (0xff << 8) | 106 | #define CLK_HS_POST (0xff << 8) |
107 | #define CLK_HS_EXIT (0xff << 16) | 107 | #define CLK_HS_EXIT (0xff << 16) |
108 | 108 | ||
109 | #define T_LPX 5 | ||
110 | #define T_HS_PREP 6 | ||
111 | #define T_HS_TRAIL 8 | ||
112 | #define T_HS_EXIT 7 | ||
113 | #define T_HS_ZERO 10 | ||
114 | |||
109 | #define NS_TO_CYCLE(n, c) ((n) / (c) + (((n) % (c)) ? 1 : 0)) | 115 | #define NS_TO_CYCLE(n, c) ((n) / (c) + (((n) % (c)) ? 1 : 0)) |
110 | 116 | ||
111 | struct phy; | 117 | struct phy; |
@@ -161,20 +167,18 @@ static void mtk_dsi_mask(struct mtk_dsi *dsi, u32 offset, u32 mask, u32 data) | |||
161 | static void dsi_phy_timconfig(struct mtk_dsi *dsi) | 167 | static void dsi_phy_timconfig(struct mtk_dsi *dsi) |
162 | { | 168 | { |
163 | u32 timcon0, timcon1, timcon2, timcon3; | 169 | u32 timcon0, timcon1, timcon2, timcon3; |
164 | unsigned int ui, cycle_time; | 170 | u32 ui, cycle_time; |
165 | unsigned int lpx; | ||
166 | 171 | ||
167 | ui = 1000 / dsi->data_rate + 0x01; | 172 | ui = 1000 / dsi->data_rate + 0x01; |
168 | cycle_time = 8000 / dsi->data_rate + 0x01; | 173 | cycle_time = 8000 / dsi->data_rate + 0x01; |
169 | lpx = 5; | ||
170 | 174 | ||
171 | timcon0 = (8 << 24) | (0xa << 16) | (0x6 << 8) | lpx; | 175 | timcon0 = T_LPX | T_HS_PREP << 8 | T_HS_ZERO << 16 | T_HS_TRAIL << 24; |
172 | timcon1 = (7 << 24) | (5 * lpx << 16) | ((3 * lpx) / 2) << 8 | | 176 | timcon1 = 4 * T_LPX | (3 * T_LPX / 2) << 8 | 5 * T_LPX << 16 | |
173 | (4 * lpx); | 177 | T_HS_EXIT << 24; |
174 | timcon2 = ((NS_TO_CYCLE(0x64, cycle_time) + 0xa) << 24) | | 178 | timcon2 = ((NS_TO_CYCLE(0x64, cycle_time) + 0xa) << 24) | |
175 | (NS_TO_CYCLE(0x150, cycle_time) << 16); | 179 | (NS_TO_CYCLE(0x150, cycle_time) << 16); |
176 | timcon3 = (2 * lpx) << 16 | NS_TO_CYCLE(80 + 52 * ui, cycle_time) << 8 | | 180 | timcon3 = NS_TO_CYCLE(0x40, cycle_time) | (2 * T_LPX) << 16 | |
177 | NS_TO_CYCLE(0x40, cycle_time); | 181 | NS_TO_CYCLE(80 + 52 * ui, cycle_time) << 8; |
178 | 182 | ||
179 | writel(timcon0, dsi->regs + DSI_PHY_TIMECON0); | 183 | writel(timcon0, dsi->regs + DSI_PHY_TIMECON0); |
180 | writel(timcon1, dsi->regs + DSI_PHY_TIMECON1); | 184 | writel(timcon1, dsi->regs + DSI_PHY_TIMECON1); |
@@ -202,19 +206,47 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi) | |||
202 | { | 206 | { |
203 | struct device *dev = dsi->dev; | 207 | struct device *dev = dsi->dev; |
204 | int ret; | 208 | int ret; |
209 | u64 pixel_clock, total_bits; | ||
210 | u32 htotal, htotal_bits, bit_per_pixel, overhead_cycles, overhead_bits; | ||
205 | 211 | ||
206 | if (++dsi->refcount != 1) | 212 | if (++dsi->refcount != 1) |
207 | return 0; | 213 | return 0; |
208 | 214 | ||
215 | switch (dsi->format) { | ||
216 | case MIPI_DSI_FMT_RGB565: | ||
217 | bit_per_pixel = 16; | ||
218 | break; | ||
219 | case MIPI_DSI_FMT_RGB666_PACKED: | ||
220 | bit_per_pixel = 18; | ||
221 | break; | ||
222 | case MIPI_DSI_FMT_RGB666: | ||
223 | case MIPI_DSI_FMT_RGB888: | ||
224 | default: | ||
225 | bit_per_pixel = 24; | ||
226 | break; | ||
227 | } | ||
228 | |||
209 | /** | 229 | /** |
210 | * data_rate = (pixel_clock / 1000) * pixel_dipth * mipi_ratio; | 230 | * vm.pixelclock is in kHz, pixel_clock unit is Hz, so multiply by 1000 |
211 | * pixel_clock unit is Khz, data_rata unit is MHz, so need divide 1000. | 231 | * htotal_time = htotal * byte_per_pixel / num_lanes |
212 | * mipi_ratio is mipi clk coefficient for balance the pixel clk in mipi. | 232 | * overhead_time = lpx + hs_prepare + hs_zero + hs_trail + hs_exit |
213 | * we set mipi_ratio is 1.05. | 233 | * mipi_ratio = (htotal_time + overhead_time) / htotal_time |
234 | * data_rate = pixel_clock * bit_per_pixel * mipi_ratio / num_lanes; | ||
214 | */ | 235 | */ |
215 | dsi->data_rate = dsi->vm.pixelclock * 3 * 21 / (1 * 1000 * 10); | 236 | pixel_clock = dsi->vm.pixelclock * 1000; |
237 | htotal = dsi->vm.hactive + dsi->vm.hback_porch + dsi->vm.hfront_porch + | ||
238 | dsi->vm.hsync_len; | ||
239 | htotal_bits = htotal * bit_per_pixel; | ||
240 | |||
241 | overhead_cycles = T_LPX + T_HS_PREP + T_HS_ZERO + T_HS_TRAIL + | ||
242 | T_HS_EXIT; | ||
243 | overhead_bits = overhead_cycles * dsi->lanes * 8; | ||
244 | total_bits = htotal_bits + overhead_bits; | ||
245 | |||
246 | dsi->data_rate = DIV_ROUND_UP_ULL(pixel_clock * total_bits, | ||
247 | htotal * dsi->lanes); | ||
216 | 248 | ||
217 | ret = clk_set_rate(dsi->hs_clk, dsi->data_rate * 1000000); | 249 | ret = clk_set_rate(dsi->hs_clk, dsi->data_rate); |
218 | if (ret < 0) { | 250 | if (ret < 0) { |
219 | dev_err(dev, "Failed to set data rate: %d\n", ret); | 251 | dev_err(dev, "Failed to set data rate: %d\n", ret); |
220 | goto err_refcount; | 252 | goto err_refcount; |