tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / autotst / dsi.c
1 /*
2  * Copyright (C) 2012 Spreadtrum Communications Inc.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13
14 #include <linux/kgdb.h>
15 #include <linux/kernel.h>
16 #include <linux/io.h>
17 #include <linux/delay.h>
18 #include <linux/clk.h>
19 #include <linux/irqreturn.h>
20 #include <linux/interrupt.h>
21
22 #include <soc/sprd/hardware.h>
23 #include <soc/sprd/globalregs.h>
24 #include <soc/sprd/irqs.h>
25 #include <soc/sprd/sci.h>
26 #include <soc/sprd/sci_glb_regs.h>
27 #include <soc/sprd/board.h>
28
29 #include "lcd_dummy.h"
30
31 #include "mipi_dsih_local.h"
32 #include "mipi_dsih_dphy.h"
33 #include "mipi_dsih_hal.h"
34 #include "mipi_dsih_api.h"
35
36 #define pr_debug printk
37
38 #define DSI_PHY_REF_CLOCK (26*1000)
39 #define DSI_EDPI_CFG (0x6c)
40
41 #ifdef CONFIG_FB_SCX15
42 #define DISPC_DPI_CLOCK                         (192*1000000/18)
43 #else
44 #define DISPC_DPI_CLOCK                         (384*1000000/36)
45 #endif
46
47 #define SPRD_MIPI_DSIC_BASE             SPRD_DSI_BASE
48 #define IRQ_DSI_INTN0                   IRQ_DSI0_INT
49 #define IRQ_DSI_INTN1                   IRQ_DSI1_INT
50
51 #define DSI_REG_EB                              REG_AP_AHB_AHB_EB
52 #define DSI_BIT_EB                                      BIT_DSI_EB
53
54 #define DSI_AHB_SOFT_RST                        REG_AP_AHB_AHB_RST
55 #define SPRD_DSI_BASE           g_dsi_base_addr
56
57 extern unsigned long g_dsi_base_addr;
58
59
60 struct autotst_dsi_context {
61         struct clk              *clk_dsi;
62         bool                    is_inited;
63         uint32_t                status;/*0- normal, 1- uninit, 2-abnormal*/
64         dsih_ctrl_t     dsi_inst;
65 };
66
67 static struct autotst_dsi_context autotst_dsi_ctx;
68
69 static uint32_t dsi_core_read_function(uint32_t addr, uint32_t offset)
70 {
71         return sci_glb_read(addr + offset, 0xffffffff);
72 }
73
74 static void dsi_core_write_function(uint32_t addr, uint32_t offset, uint32_t data)
75 {
76         sci_glb_write((addr + offset), data, 0xffffffff);
77 }
78
79 static void dsi_core_or_function(unsigned int addr,unsigned int data)
80 {
81         sci_glb_write(addr,(sci_glb_read(addr, 0xffffffff) | data), 0xffffffff);
82 }
83 static void dsi_core_and_function(unsigned int addr,unsigned int data)
84 {
85         sci_glb_write(addr,(sci_glb_read(addr, 0xffffffff) & data), 0xffffffff);
86 }
87
88 #if 0
89 static irqreturn_t dsi_isr0(int irq, void *data)
90 {
91         uint32_t reg_val = dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_ST0);
92         printk(KERN_ERR "autotst_dsi: [%s](0x%x)!\n", __FUNCTION__, reg_val);
93         return IRQ_HANDLED;
94 }
95
96 static irqreturn_t dsi_isr1(int irq, void *data)
97 {
98         uint32_t reg_val = dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_ST1);
99         printk(KERN_ERR "autotst_dsi: [%s](0x%x)!\n", __FUNCTION__, reg_val);
100         return IRQ_HANDLED;
101 }
102 #endif
103
104 static int32_t dsi_edpi_setbuswidth(struct info_mipi * mipi)
105 {
106         dsih_color_coding_t color_coding = 0;
107
108         switch(mipi->video_bus_width){
109         case 16:
110                 color_coding = COLOR_CODE_16BIT_CONFIG1;
111                 break;
112         case 18:
113                 color_coding = COLOR_CODE_18BIT_CONFIG1;
114                 break;
115         case 24:
116                 color_coding = COLOR_CODE_24BIT;
117                 break;
118         default:
119                 printk(KERN_ERR "autotst_dsi:[%s] fail, invalid video_bus_width\n", __FUNCTION__);
120                 return 0;
121         }
122
123 #ifdef FB_DSIH_VERSION_1P21A
124         dsi_core_and_function((SPRD_MIPI_DSIC_BASE+R_DSI_HOST_DPI_COLOR_CODE),0xfffffff0);
125         dsi_core_or_function((SPRD_MIPI_DSIC_BASE+R_DSI_HOST_DPI_COLOR_CODE),color_coding);
126 #else
127         dsi_core_write_function(SPRD_MIPI_DSIC_BASE,  R_DSI_HOST_DPI_CFG, ((uint32_t)color_coding<<2));
128 #endif
129         return 0;
130 }
131
132
133 static int32_t dsi_edpi_init(void)
134 {
135 #ifdef FB_DSIH_VERSION_1P21A
136         dsi_core_write_function((uint32_t)SPRD_MIPI_DSIC_BASE,  (uint32_t)R_DSI_HOST_EDPI_CMD_SIZE, 0x500);
137 #else
138         dsi_core_write_function((uint32_t)SPRD_MIPI_DSIC_BASE,  (uint32_t)DSI_EDPI_CFG, 0x10500);
139 #endif
140         return 0;
141 }
142
143 static int32_t dsi_dpi_init(struct panel_spec* panel)
144 {
145         dsih_dpi_video_t dpi_param;
146         dsih_error_t result;
147         struct info_mipi * mipi = panel->info.mipi;
148
149         dpi_param.no_of_lanes = mipi->lan_number;
150         dpi_param.byte_clock = mipi->phy_feq / 8;
151         dpi_param.pixel_clock = DISPC_DPI_CLOCK / 1000;
152 #ifdef FB_DSIH_VERSION_1P21A
153         dpi_param.max_hs_to_lp_cycles = 4;//110;
154         dpi_param.max_lp_to_hs_cycles = 15;//10;
155 #endif
156
157         switch(mipi->video_bus_width){
158         case 16:
159                 dpi_param.color_coding = COLOR_CODE_16BIT_CONFIG1;
160                 break;
161         case 18:
162                 dpi_param.color_coding = COLOR_CODE_18BIT_CONFIG1;
163                 break;
164         case 24:
165                 dpi_param.color_coding = COLOR_CODE_24BIT;
166                 break;
167         default:
168                 printk(KERN_ERR "autotst_dsi:[%s] fail, invalid video_bus_width\n", __FUNCTION__);
169                 break;
170         }
171
172         if(SPRDFB_POLARITY_POS == mipi ->h_sync_pol){
173                 dpi_param.h_polarity = 1;
174         }
175
176         if(SPRDFB_POLARITY_POS == mipi ->v_sync_pol){
177                 dpi_param.v_polarity = 1;
178         }
179
180         if(SPRDFB_POLARITY_POS == mipi ->de_pol){
181                 dpi_param.data_en_polarity = 1;
182         }
183
184         dpi_param.h_active_pixels = panel->width;
185         dpi_param.h_sync_pixels = mipi->timing->hsync;
186         dpi_param.h_back_porch_pixels = mipi->timing->hbp;
187         dpi_param.h_total_pixels = panel->width + mipi->timing->hsync + mipi->timing->hbp + mipi->timing->hfp;
188
189         dpi_param.v_active_lines = panel->height;
190         dpi_param.v_sync_lines = mipi->timing->vsync;
191         dpi_param.v_back_porch_lines = mipi->timing->vbp;
192         dpi_param.v_total_lines = panel->height + mipi->timing->vsync + mipi->timing->vbp + mipi->timing->vfp;
193
194         dpi_param.receive_ack_packets = 0;
195         dpi_param.video_mode = VIDEO_BURST_WITH_SYNC_PULSES;
196         dpi_param.virtual_channel = 0;
197         dpi_param.is_18_loosely = 0;
198
199         result = mipi_dsih_dpi_video(&(autotst_dsi_ctx.dsi_inst), &dpi_param);
200         if(result != OK){
201                 printk(KERN_ERR "autotst_dsi: [%s] mipi_dsih_dpi_video fail (%d)!\n", __FUNCTION__, result);
202                 return -1;
203         }
204
205         return 0;
206 }
207
208 static void dsi_log_error(const char * string)
209 {
210         printk(string);
211 }
212
213 static int32_t dsi_module_init(struct panel_spec *panel)
214 {
215         int ret = 0;
216         dsih_ctrl_t* dsi_instance = &(autotst_dsi_ctx.dsi_inst);
217         dphy_t *phy = &(dsi_instance->phy_instance);
218         struct info_mipi * mipi = panel->info.mipi;
219
220         pr_debug(KERN_INFO "autotst_dsi:[%s]\n", __FUNCTION__);
221
222         if(autotst_dsi_ctx.is_inited){
223                 printk(KERN_INFO "autotst_dsi: dsi_module_init. is_inited==true!");
224                 return 0;
225         }
226         else{
227                 printk(KERN_INFO "autotst_dsi: dsi_module_init. call only once!\n");
228         }
229
230         phy->address = SPRD_MIPI_DSIC_BASE;
231         phy->core_read_function = dsi_core_read_function;
232         phy->core_write_function = dsi_core_write_function;
233         phy->log_error = dsi_log_error;
234         phy->log_info = NULL;
235         phy->reference_freq = DSI_PHY_REF_CLOCK;
236
237         dsi_instance->address = SPRD_MIPI_DSIC_BASE;
238         dsi_instance->color_mode_polarity =mipi->color_mode_pol;
239         dsi_instance->shut_down_polarity = mipi->shut_down_pol;
240         dsi_instance->core_read_function = dsi_core_read_function;
241         dsi_instance->core_write_function = dsi_core_write_function;
242         dsi_instance->log_error = dsi_log_error;
243         dsi_instance->log_info = NULL;
244          /*in our rtl implementation, this is max rd time, not bta time and use 15bits*/
245         dsi_instance->max_bta_cycles = 0x6000;//10;
246 #ifndef FB_DSIH_VERSION_1P21A
247         dsi_instance->max_hs_to_lp_cycles = 4;//110;
248         dsi_instance->max_lp_to_hs_cycles = 15;//10;
249 #endif
250         dsi_instance->max_lanes = mipi->lan_number;
251 #if 0
252         ret = request_irq(IRQ_DSI_INTN0, dsi_isr0, IRQF_DISABLED, "DSI_INT0", &autotst_dsi_ctx);
253         if (ret) {
254                 printk(KERN_ERR "autotst_dsi: dsi failed to request irq int0!\n");
255         }else{
256                 printk(KERN_ERR "autotst_dsi: dsi request irq int0 OK!\n");
257         }
258
259         ret = request_irq(IRQ_DSI_INTN1, dsi_isr1, IRQF_DISABLED, "DSI_INT1", &autotst_dsi_ctx);
260         if (ret) {
261                 printk(KERN_ERR "autotst_dsi: dsi failed to request irq int1!\n");
262         }else{
263                 printk(KERN_ERR "autotst_dsi: dsi request irq int1 OK!\n");
264         }
265 #endif
266         autotst_dsi_ctx.is_inited = true;
267
268         return 0;
269 }
270
271 static int32_t dsih_init(struct panel_spec *panel)
272 {
273         dsih_error_t result = OK;
274         dsih_ctrl_t* dsi_instance = &(autotst_dsi_ctx.dsi_inst);
275         dphy_t *phy = &(dsi_instance->phy_instance);
276         struct info_mipi * mipi = panel->info.mipi;
277         int i = 0;
278 #ifdef FB_DSIH_VERSION_1P21A
279         dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_MSK0, 0x1fffff);
280         dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_MSK1, 0x3ffff);
281 #else
282         dsi_core_write_function(SPRD_MIPI_DSIC_BASE,  R_DSI_HOST_ERROR_MSK0, 0x1fffff);
283         dsi_core_write_function(SPRD_MIPI_DSIC_BASE,  R_DSI_HOST_ERROR_MSK1, 0x3ffff);
284 #endif
285
286         if(SPRDFB_MIPI_MODE_CMD == mipi->work_mode){
287                 dsi_edpi_init();
288         }
289
290 #ifndef FB_DSIH_VERSION_1P21A
291         dsi_instance->phy_feq = panel->info.mipi->phy_feq;
292 #endif
293         result = mipi_dsih_open(dsi_instance);
294         if(OK != result){
295                 printk(KERN_ERR "autotst_dsi: [%s]: mipi_dsih_open fail (%d)!\n", __FUNCTION__, result);
296                 autotst_dsi_ctx.status = 1;
297                 return -1;
298         }
299
300         result = mipi_dsih_dphy_configure(phy,  mipi->lan_number, mipi->phy_feq);
301         if(OK != result){
302                 printk(KERN_ERR "autotst_dsi: [%s]: mipi_dsih_dphy_configure fail (%d)!\n", __FUNCTION__, result);
303                 autotst_dsi_ctx.status = 1;
304                 return -1;
305         }
306
307         while(5 != (dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PHY_STATUS) & 5)){
308                 if(0x0 == ++i%500000){
309                         printk("autotst_dsi: [%s] warning: busy waiting!\n", __FUNCTION__);
310                 }
311         }
312
313         if(SPRDFB_MIPI_MODE_CMD == mipi->work_mode){
314                 dsi_edpi_setbuswidth(mipi);
315         }
316
317         result = mipi_dsih_enable_rx(dsi_instance, 1);
318         if(OK != result){
319                 printk(KERN_ERR "autotst_dsi: [%s]: mipi_dsih_enable_rx fail (%d)!\n", __FUNCTION__, result);
320                 autotst_dsi_ctx.status = 1;
321                 return -1;
322         }
323
324         result = mipi_dsih_ecc_rx(dsi_instance, 1);
325         if(OK != result){
326                 printk(KERN_ERR "autotst_dsi: [%s]: mipi_dsih_ecc_rx fail (%d)!\n", __FUNCTION__, result);
327                 autotst_dsi_ctx.status = 1;
328                 return -1;
329         }
330
331         result = mipi_dsih_eotp_rx(dsi_instance, 1);
332         if(OK != result){
333                 printk(KERN_ERR "autotst_dsi: [%s]: mipi_dsih_eotp_rx fail (%d)!\n", __FUNCTION__, result);
334                 autotst_dsi_ctx.status = 1;
335                 return -1;
336         }
337
338         result = mipi_dsih_eotp_tx(dsi_instance, 1);
339         if(OK != result){
340                 printk(KERN_ERR "autotst_dsi: [%s]: mipi_dsih_eotp_tx fail (%d)!\n", __FUNCTION__, result);
341                 autotst_dsi_ctx.status = 1;
342                 return -1;
343         }
344
345         if(SPRDFB_MIPI_MODE_VIDEO == mipi->work_mode){
346                 dsi_dpi_init(panel);
347         }
348
349 #ifdef FB_DSIH_VERSION_1P21A
350         mipi_dsih_dphy_enable_nc_clk(&(dsi_instance->phy_instance), false);
351 #endif
352         autotst_dsi_ctx.status = 0;
353
354         return 0;
355 }
356
357 static void dsi_enable(void)
358 {
359         sci_glb_set(REG_AP_AHB_MISC_CKG_EN, BIT_DPHY_REF_CKG_EN);
360         sci_glb_set(REG_AP_AHB_MISC_CKG_EN, BIT_DPHY_CFG_CKG_EN);
361         sci_glb_set(DSI_REG_EB, DSI_BIT_EB);
362 }
363
364 static void dsi_disable(void)
365 {
366         sci_glb_clr(REG_AP_AHB_MISC_CKG_EN, BIT_DPHY_REF_CKG_EN);
367         sci_glb_clr(REG_AP_AHB_MISC_CKG_EN, BIT_DPHY_CFG_CKG_EN);
368         sci_glb_clr(DSI_REG_EB, DSI_BIT_EB);
369 }
370
371 static void dsi_reset(void)
372 {
373         sci_glb_set(DSI_AHB_SOFT_RST, BIT_DSI_SOFT_RST);
374         udelay(10);
375         sci_glb_clr(DSI_AHB_SOFT_RST, BIT_DSI_SOFT_RST);
376 }
377
378 static int32_t dsi_ready(struct panel_spec *panel)
379 {
380         struct info_mipi * mipi = panel->info.mipi;
381
382         if(SPRDFB_MIPI_MODE_CMD == mipi->work_mode){
383                 mipi_dsih_cmd_mode(&(autotst_dsi_ctx.dsi_inst), 1);
384 #ifdef FB_DSIH_VERSION_1P21A
385                 mipi_dsih_dphy_enable_hs_clk(&(autotst_dsi_ctx.dsi_inst.phy_instance), true);
386 #else
387                 dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_CMD_MODE_CFG, 0x1);
388                 dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PHY_IF_CTRL, 0x1);
389 #endif
390         }else{
391 #ifdef FB_DSIH_VERSION_1P21A
392                 mipi_dsih_dphy_enable_hs_clk(&(autotst_dsi_ctx.dsi_inst.phy_instance), true);
393 #else
394                 dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PHY_IF_CTRL, 0x1);
395 #endif
396                 mipi_dsih_video_mode(&(autotst_dsi_ctx.dsi_inst), 1);
397                 dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PWR_UP, 0);
398                 udelay(100);
399                 dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PWR_UP, 1);
400                 mdelay(3);
401 #ifdef FB_DSIH_VERSION_1P21A
402                 dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_ST0);
403                 dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_ST1);
404 #else
405                 dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_ST0);
406                 dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_ST1);
407 #endif
408         }
409
410 #ifdef FB_DSIH_VERSION_1P21A
411         //dsi_core_write_function(SPRD_MIPI_DSIC_BASE,  R_DSI_HOST_INT_MSK0, 0x0);
412         //dsi_core_write_function(SPRD_MIPI_DSIC_BASE,  R_DSI_HOST_INT_MSK1, 0x800);
413 #else
414         //dsi_core_write_function(SPRD_MIPI_DSIC_BASE,  R_DSI_HOST_ERROR_MSK0, 0x0);
415         //dsi_core_write_function(SPRD_MIPI_DSIC_BASE,  R_DSI_HOST_ERROR_MSK1, 0x800);
416 #endif
417         return 0;
418 }
419
420 void autotst_dsi_dump(void)
421 {
422     int i = 0;
423     for(i=0;i<256;i+=16){
424         printk("autotst_dsi: %x: 0x%x, 0x%x, 0x%x, 0x%x\n", i, dsi_core_read_function(SPRD_MIPI_DSIC_BASE, i),
425             dsi_core_read_function(SPRD_MIPI_DSIC_BASE, i+4),
426             dsi_core_read_function(SPRD_MIPI_DSIC_BASE, i+8),
427             dsi_core_read_function(SPRD_MIPI_DSIC_BASE, i+12));
428     }
429     printk("**************************\n");
430 }
431
432 void autotst_dsi_dump1(void)
433 {
434     int i = 0;
435     for(i=0;i<50;i++){
436         printk("autotst_dsi: 0x%x\n", dsi_core_read_function(SPRD_MIPI_DSIC_BASE, 0x60));
437         udelay(5);
438     }
439     printk("**************************\n");
440 }
441
442 int32_t autotst_dsi_init(struct panel_spec *panel)
443 {
444         dsih_error_t result = OK;
445
446         printk(KERN_INFO "autotst_dsi:[%s]\n", __FUNCTION__);
447         dsi_enable();
448         dsi_reset();
449         dsi_module_init(panel);
450         result=dsih_init(panel);
451         dsi_ready(panel);
452
453         return result;
454 }
455
456 int32_t autotst_dsi_uninit(void)
457 {
458         dsih_error_t result;
459         dsih_ctrl_t* dsi_instance = &(autotst_dsi_ctx.dsi_inst);
460
461         printk(KERN_INFO "autotst_dsi: [%s]\n",__FUNCTION__);
462
463         dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PHY_IF_CTRL, 0);
464         result = mipi_dsih_close(&(autotst_dsi_ctx.dsi_inst));
465         dsi_instance->status = NOT_INITIALIZED;
466
467         autotst_dsi_ctx.status = 1;
468
469         if(OK != result){
470                 printk(KERN_ERR "autotst_dsi: [%s] fail (%d)!\n", __FUNCTION__, result);
471                 return -1;
472         }
473
474         mdelay(10);
475         dsi_disable();
476         return 0;
477 }