tizen 2.4 release
[kernel/u-boot-tm1.git] / drivers / video / sc8825fb / sprdfb_dsi.c
1 /*\r
2  * Copyright (C) 2012 Spreadtrum Communications Inc.\r
3  *\r
4  * This software is licensed under the terms of the GNU General Public\r
5  * License version 2, as published by the Free Software Foundation, and\r
6  * may be copied, distributed, and modified under those terms.\r
7  *\r
8  * This program is distributed in the hope that it will be useful,\r
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
11  * GNU General Public License for more details.\r
12  */\r
13 #include <common.h>\r
14 \r
15 #include <asm/arch/tiger_lcd.h>\r
16 \r
17 #include <asm/io.h>\r
18 #include <asm/arch/sc8810_reg_ahb.h>\r
19 #include <asm/arch/sc8810_reg_base.h>
20 \r
21 \r
22 #include "sprdfb.h"\r
23 \r
24 #include "mipi_dsih_local.h"\r
25 #include "mipi_dsih_dphy.h"\r
26 #include "mipi_dsih_hal.h"\r
27 #include "mipi_dsih_api.h"\r
28 \r
29 #define DSI_SOFT_RST (26)\r
30 #define DSI_PHY_REF_CLOCK (26*1000)\r
31 \r
32 #define DSI_EDPI_CFG (0x6c)\r
33 \r
34 \r
35 struct sprdfb_dsi_context {\r
36         uint16_t                        is_inited;\r
37 \r
38         dsih_ctrl_t     dsi_inst;\r
39 };\r
40 \r
41 static struct sprdfb_dsi_context dsi_ctx;\r
42 \r
43 static void __raw_bits_and(unsigned int v, unsigned int a)
44 {
45         __raw_writel((__raw_readl(a) & v), a);
46 }
47
48 static void __raw_bits_or(unsigned int v, unsigned int a)
49 {
50         __raw_writel((__raw_readl(a) | v), a);
51 }
52 \r
53 \r
54 static uint32_t dsi_core_read_function(uint32_t addr, uint32_t offset)\r
55 {\r
56         return __raw_readl(addr + offset);\r
57 }\r
58 \r
59 static void dsi_core_write_function(uint32_t addr, uint32_t offset, uint32_t data)\r
60 {\r
61         __raw_writel(data, addr + offset);\r
62 }\r
63 \r
64 \r
65 static void dsi_reset(void)\r
66 {\r
67         __raw_writel(__raw_readl(AHB_SOFT_RST) | (1<<DSI_SOFT_RST), AHB_SOFT_RST);\r
68         udelay(10);
69         __raw_writel(__raw_readl(AHB_SOFT_RST) & (~(1<<DSI_SOFT_RST)),AHB_SOFT_RST);\r
70 }\r
71 \r
72 int32_t dsi_early_int(void)\r
73 {\r
74         FB_PRINT("sprdfb:[%s]\n", __FUNCTION__);\r
75 \r
76         if(dsi_ctx.is_inited){\r
77                 FB_PRINT("sprdfb: dispc early init warning!(has been inited)");\r
78                 return 0;
79         }
80 \r
81         //TODO:Enable DSI clock\r
82 \r
83         dsi_reset();\r
84 \r
85         memset(&(dsi_ctx.dsi_inst), 0, sizeof(dsi_ctx.dsi_inst));\r
86 \r
87         dsi_ctx.is_inited = 1;\r
88         return 0;\r
89 }\r
90 \r
91 static int32_t dsi_edpi_setbuswidth(struct info_mipi * mipi)
92 {\r
93         dsih_color_coding_t color_coding = 0;\r
94 \r
95         switch(mipi->video_bus_width){\r
96         case 16:\r
97                 color_coding = COLOR_CODE_16BIT_CONFIG1;\r
98                 break;\r
99         case 18:\r
100                 color_coding = COLOR_CODE_18BIT_CONFIG1;\r
101                 break;\r
102         case 24:\r
103                 color_coding = COLOR_CODE_24BIT;\r
104                 break;\r
105         default:\r
106                 FB_PRINT("sprdfb:[%s] fail, invalid video_bus_width\n", __FUNCTION__);\r
107                 break;\r
108         }\r
109 \r
110         dsi_core_write_function(DSI_CTL_BEGIN,  R_DSI_HOST_DPI_CFG, (uint32_t)(color_coding<<2));\r
111         return 0;\r
112 }\r
113 \r
114 \r
115 static int32_t dsi_edpi_init(void)\r
116 {\r
117         dsi_core_write_function((uint32_t)DSI_CTL_BEGIN,  (uint32_t)DSI_EDPI_CFG, 0x10500);
118         return 0;
119 }
120 \r
121 static int32_t dsi_dpi_init(struct panel_spec* panel)\r
122 {\r
123         dsih_dpi_video_t dpi_param;\r
124         dsih_error_t result;\r
125         struct info_mipi * mipi = panel->info.mipi;\r
126 \r
127         dpi_param.no_of_lanes = mipi->lan_number;\r
128         dpi_param.byte_clock = mipi->phy_feq / 8;\r
129         dpi_param.pixel_clock = 384*1000/11;//DSI_PHY_REF_CLOCK / 4;\r
130 \r
131         switch(mipi->video_bus_width){\r
132         case 16:\r
133                 dpi_param.color_coding = COLOR_CODE_16BIT_CONFIG1;\r
134                 break;\r
135         case 18:\r
136                 dpi_param.color_coding = COLOR_CODE_18BIT_CONFIG1;\r
137                 break;\r
138         case 24:\r
139                 dpi_param.color_coding = COLOR_CODE_24BIT;\r
140                 break;\r
141         default:\r
142                 FB_PRINT("sprdfb:[%s] fail, invalid video_bus_width\n", __FUNCTION__);\r
143                 break;\r
144         }\r
145 \r
146         //if(SPRDFB_POLARITY_POS == mipi ->h_sync_pol){\r
147                 dpi_param.h_polarity = 1;\r
148         //}\r
149 \r
150         //if(SPRDFB_POLARITY_POS == mipi ->v_sync_pol){\r
151                 dpi_param.v_polarity = 1;\r
152         //}\r
153 \r
154         //if(SPRDFB_POLARITY_POS == mipi ->de_pol){\r
155                 dpi_param.data_en_polarity = 1;\r
156         //}\r
157 \r
158         dpi_param.h_active_pixels = panel->width;\r
159         dpi_param.h_sync_pixels = mipi->timing->hsync;\r
160         dpi_param.h_back_porch_pixels = mipi->timing->hbp;\r
161         dpi_param.h_total_pixels = panel->width + mipi->timing->hsync + mipi->timing->hbp + mipi->timing->hfp;\r
162 \r
163         dpi_param.v_active_lines = panel->height;\r
164         dpi_param.v_sync_lines = mipi->timing->vsync;\r
165         dpi_param.v_back_porch_lines = mipi->timing->vbp;\r
166         dpi_param.v_total_lines = panel->height + mipi->timing->vsync + mipi->timing->vbp + mipi->timing->vfp;\r
167 \r
168         dpi_param.receive_ack_packets = 0;\r
169         dpi_param.video_mode = VIDEO_BURST_WITH_SYNC_PULSES;\r
170         dpi_param.virtual_channel = 0;\r
171         dpi_param.is_18_loosely = 0;\r
172 \r
173         result = mipi_dsih_dpi_video(&(dsi_ctx.dsi_inst), &dpi_param);\r
174         if(result != OK){\r
175                 FB_PRINT("sprdfb: [%s] mipi_dsih_dpi_video fail (%d)!\n", __FUNCTION__, result);\r
176                 return -1;\r
177         }\r
178 \r
179         return 0;\r
180 }\r
181 \r
182 static void dsi_log_error(const char * string)\r
183 {\r
184         FB_PRINT(string);\r
185 }\r
186 \r
187 \r
188 int32_t sprdfb_dsi_init(struct sprdfb_device *dev)\r
189 {\r
190         dsih_error_t result = OK;\r
191         dsih_ctrl_t* dsi_instance = &(dsi_ctx.dsi_inst);\r
192         dphy_t *phy = &(dsi_instance->phy_instance);\r
193         struct info_mipi * mipi = dev->panel->info.mipi;\r
194 \r
195         __raw_bits_or((1<<0), 0x2090021c);  //enable dphy\r
196 \r
197         FB_PRINT("sprdfb:[%s]\n", __FUNCTION__);\r
198 \r
199         dsi_early_int();\r
200 \r
201         phy->address = DSI_CTL_BEGIN;\r
202         phy->core_read_function = dsi_core_read_function;\r
203         phy->core_write_function = dsi_core_write_function;\r
204         phy->log_error = dsi_log_error;\r
205         phy->log_info = NULL;\r
206         phy->reference_freq = DSI_PHY_REF_CLOCK;\r
207 \r
208         dsi_instance->address = DSI_CTL_BEGIN;\r
209         dsi_instance->color_mode_polarity =SPRDFB_POLARITY_NEG; //mipi->color_mode_pol;\r
210         dsi_instance->shut_down_polarity = SPRDFB_POLARITY_NEG; //mipi->shut_down_pol;\r
211         dsi_instance->core_read_function = dsi_core_read_function;\r
212         dsi_instance->core_write_function = dsi_core_write_function;\r
213         dsi_instance->log_error = dsi_log_error;\r
214         dsi_instance->log_info = NULL;\r
215         /*in our rtl implementation, this is max rd time, not bta time and use 15bits*/\r
216         dsi_instance->max_bta_cycles = 0x6000;//10;\r
217         dsi_instance->max_hs_to_lp_cycles = 4;//110;\r
218         dsi_instance->max_lp_to_hs_cycles = 15;//10;\r
219         dsi_instance->max_lanes = mipi->lan_number;\r
220 \r
221         if(SPRDFB_MIPI_MODE_CMD == mipi->work_mode){\r
222                 dsi_edpi_init();\r
223         }/*else{\r
224                 dsi_dpi_init(dev->panel);\r
225         }*/\r
226 \r
227 /*\r
228         result = mipi_dsih_unregister_all_events(dsi_instance);\r
229         if(OK != result){\r
230                 FB_PRINT("sprdfb: [%s]: mipi_dsih_unregister_all_events fail (%d)!\n", __FUNCTION__, result);\r
231                 return -1;\r
232         }\r
233 */\r
234         dsi_core_write_function(DSI_CTL_BEGIN,  R_DSI_HOST_ERROR_MSK0, 0x1fffff);\r
235         dsi_core_write_function(DSI_CTL_BEGIN,  R_DSI_HOST_ERROR_MSK1, 0x3ffff);\r
236 \r
237         result = mipi_dsih_open(dsi_instance);\r
238         if(OK != result){\r
239                 FB_PRINT("sprdfb: [%s]: mipi_dsih_open fail (%d)!\n", __FUNCTION__, result);\r
240                 return -1;\r
241         }\r
242 \r
243         result = mipi_dsih_dphy_configure(phy,  mipi->lan_number, mipi->phy_feq);\r
244         if(OK != result){\r
245                 FB_PRINT("sprdfb: [%s]: mipi_dsih_dphy_configure fail (%d)!\n", __FUNCTION__, result);\r
246                 return -1;\r
247         }\r
248 \r
249         while(5 != (dsi_core_read_function(DSI_CTL_BEGIN, R_DSI_HOST_PHY_STATUS) & 5));\r
250 \r
251         if(SPRDFB_MIPI_MODE_CMD == mipi->work_mode){\r
252                 dsi_edpi_setbuswidth(mipi);\r
253         }\r
254 \r
255         result = mipi_dsih_enable_rx(dsi_instance, 1);\r
256         if(OK != result){\r
257                 FB_PRINT("sprdfb: [%s]: mipi_dsih_enable_rx fail (%d)!\n", __FUNCTION__, result);\r
258                 return -1;\r
259         }\r
260 \r
261         result = mipi_dsih_ecc_rx(dsi_instance, 1);\r
262         if(OK != result){\r
263                 FB_PRINT("sprdfb: [%s]: mipi_dsih_ecc_rx fail (%d)!\n", __FUNCTION__, result);\r
264                 return -1;\r
265         }\r
266 \r
267         result = mipi_dsih_eotp_rx(dsi_instance, 1);\r
268         if(OK != result){\r
269                 FB_PRINT("sprdfb: [%s]: mipi_dsih_eotp_rx fail (%d)!\n", __FUNCTION__, result);\r
270                 return -1;\r
271         }\r
272 \r
273         result = mipi_dsih_eotp_tx(dsi_instance, 1);\r
274         if(OK != result){\r
275                 FB_PRINT("sprdfb: [%s]: mipi_dsih_eotp_tx fail (%d)!\n", __FUNCTION__, result);\r
276                 return -1;\r
277         }\r
278 \r
279         if(SPRDFB_MIPI_MODE_VIDEO == mipi->work_mode){\r
280                 dsi_dpi_init(dev->panel);\r
281         }\r
282 \r
283         return 0;\r
284 }\r
285 \r
286 int32_t sprdfb_dsi_uninit(struct sprdfb_device *dev)\r
287 {\r
288         dsih_error_t result;\r
289         result = mipi_dsih_close(&(dsi_ctx.dsi_inst));\r
290         if(OK != result){\r
291                 FB_PRINT("sprdfb: [%s]: sprdfb_dsi_uninit fail (%d)!\n", __FUNCTION__, result);\r
292                 return -1;\r
293         } else {\r
294                 dsi_ctx.is_inited = 0;\r
295         }\r
296 \r
297         dsi_core_write_function(DSI_CTL_BEGIN, R_DSI_HOST_PHY_IF_CTRL, 0);\r
298         mdelay(3);\r
299 \r
300         return 0;\r
301 }\r
302 \r
303 int32_t sprdfb_dsi_ready(struct sprdfb_device *dev)\r
304 {\r
305         struct info_mipi * mipi = dev->panel->info.mipi;\r
306 \r
307         if(SPRDFB_MIPI_MODE_CMD == mipi->work_mode){\r
308                 mipi_dsih_cmd_mode(&(dsi_ctx.dsi_inst), 1);\r
309                 dsi_core_write_function(DSI_CTL_BEGIN, R_DSI_HOST_CMD_MODE_CFG, 0x1);\r
310                 dsi_core_write_function(DSI_CTL_BEGIN, R_DSI_HOST_PHY_IF_CTRL, 0x1);\r
311         }else{\r
312                 mipi_dsih_video_mode(&(dsi_ctx.dsi_inst), 1);\r
313                 dsi_core_write_function(DSI_CTL_BEGIN, R_DSI_HOST_PWR_UP, 0);\r
314                 udelay(100);\r
315                 dsi_core_write_function(DSI_CTL_BEGIN, R_DSI_HOST_PWR_UP, 1);\r
316                 udelay(10*1000);\r
317                 dsi_core_read_function(DSI_CTL_BEGIN, R_DSI_HOST_ERROR_ST0);\r
318                 dsi_core_read_function(DSI_CTL_BEGIN, R_DSI_HOST_ERROR_ST1);\r
319         }\r
320         return 0;\r
321 }\r
322 \r
323 static int32_t sprdfb_dsi_set_cmd_mode(void)\r
324 {\r
325         mipi_dsih_cmd_mode(&(dsi_ctx.dsi_inst), 1);\r
326         return 0;\r
327 }\r
328 \r
329 static int32_t sprdfb_dsi_set_video_mode(void)\r
330 {\r
331         mipi_dsih_video_mode(&(dsi_ctx.dsi_inst), 1);\r
332         return 0;\r
333 }\r
334 \r
335 static int32_t sprdfb_dsi_gen_write(uint8_t *param, uint16_t param_length)\r
336 {\r
337         dsih_error_t result;\r
338         result = mipi_dsih_gen_wr_cmd(&(dsi_ctx.dsi_inst), 0, param, param_length);\r
339         if(OK != result){\r
340                 FB_PRINT("sprdfb: [%s] error (%d)\n", __FUNCTION__, result);\r
341                 return -1;\r
342         }\r
343         return 0;\r
344 }\r
345 \r
346 static int32_t sprdfb_dsi_gen_read(uint8_t *param, uint16_t param_length, uint8_t bytes_to_read, uint8_t *read_buffer)\r
347 {\r
348         uint16_t result;\r
349         result = mipi_dsih_gen_rd_cmd(&(dsi_ctx.dsi_inst), 0, param, param_length, bytes_to_read, read_buffer);\r
350         if(0 == result){\r
351                 FB_PRINT("sprdfb: [%s] error (%d)\n", __FUNCTION__, result);\r
352                 return -1;\r
353         }\r
354         return 0;\r
355 }\r
356 \r
357 static int32_t sprdfb_dsi_dcs_write(uint8_t *param, uint16_t param_length)\r
358 {\r
359         dsih_error_t result;\r
360         result = mipi_dsih_dcs_wr_cmd(&(dsi_ctx.dsi_inst), 0, param, param_length);\r
361         if(OK != result){\r
362                 FB_PRINT("sprdfb: [%s] error (%d)\n", __FUNCTION__, result);\r
363                 return -1;\r
364         }\r
365         return 0;\r
366 }\r
367 \r
368 static int32_t sprdfb_dsi_dcs_read(uint8_t command, uint8_t bytes_to_read, uint8_t *read_buffer)\r
369 {\r
370         uint16_t result;\r
371         result = mipi_dsih_dcs_rd_cmd(&(dsi_ctx.dsi_inst), 0, command, bytes_to_read, read_buffer);\r
372         if(0 == result){\r
373                 FB_PRINT("sprdfb: [%s] error (%d)\n", __FUNCTION__, result);\r
374                 return -1;\r
375         }\r
376         return 0;\r
377 }\r
378 \r
379 static int32_t sprd_dsi_force_write(uint8_t data_type, uint8_t *p_params, uint16_t param_length)\r
380 {\r
381         int32_t iRtn = 0;\r
382         iRtn = mipi_dsih_gen_wr_packet(&(dsi_ctx.dsi_inst), 0, data_type,  p_params, param_length);\r
383         return iRtn;\r
384 }\r
385 \r
386 static int32_t sprd_dsi_force_read(uint8_t command, uint8_t bytes_to_read, uint8_t * read_buffer)\r
387 {\r
388         int32_t iRtn = 0;\r
389         dsih_ctrl_t *curInstancePtr = &(dsi_ctx.dsi_inst);\r
390 \r
391         mipi_dsih_eotp_rx(curInstancePtr, 0);\r
392         mipi_dsih_eotp_tx(curInstancePtr, 0);\r
393 \r
394         iRtn = mipi_dsih_gen_rd_packet(&(dsi_ctx.dsi_inst),  0,  6,  0, command,  bytes_to_read, read_buffer);\r
395 \r
396         mipi_dsih_eotp_rx(curInstancePtr, 1);\r
397         mipi_dsih_eotp_tx(curInstancePtr, 1);\r
398 \r
399         return iRtn;\r
400 }\r
401 \r
402 struct ops_mipi sprdfb_mipi_ops = {\r
403         .mipi_set_cmd_mode = sprdfb_dsi_set_cmd_mode,\r
404         .mipi_set_video_mode = sprdfb_dsi_set_video_mode,\r
405         .mipi_gen_write = sprdfb_dsi_gen_write,\r
406         .mipi_gen_read = sprdfb_dsi_gen_read,\r
407         .mipi_dcs_write = sprdfb_dsi_dcs_write,\r
408         .mipi_dcs_read = sprdfb_dsi_dcs_read,\r
409         .mipi_force_write = sprd_dsi_force_write,\r
410         .mipi_force_read = sprd_dsi_force_read,\r
411 \r
412 };\r
413 \r
414 \r
415 \r