tizen 2.4 release
[kernel/u-boot-tm1.git] / drivers / video / sc8825fb / sprdfb_rgb.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 #include <asm/arch/dispc_reg.h>\r
17 \r
18 #include "sprdfb.h"\r
19 \r
20 extern struct ops_i2c sprdfb_i2c_ops;\r
21 extern struct ops_spi sprdfb_spi_ops;\r
22 \r
23 extern uint16_t sprdfb_i2c_init(struct sprdfb_device *dev);\r
24 extern uint16_t sprdfb_i2c_uninit(struct sprdfb_device *dev);\r
25 extern uint16_t sprdfb_spi_init(struct sprdfb_device *dev);\r
26 extern uint16_t sprdfb_spi_uninit(struct sprdfb_device *dev);\r
27 \r
28 \r
29 static uint32_t rgb_readid(struct panel_spec *self)\r
30 {\r
31         uint32_t id = 0;\r
32         struct info_rgb *rgb = self->info.rgb;\r
33 \r
34         /* default id reg is 0 */\r
35         if(SPRDFB_RGB_BUS_TYPE_I2C == rgb->cmd_bus_mode){\r
36                 rgb->bus_info.i2c->ops->i2c_read_16bits(rgb->bus_info.i2c->i2c_addr , 0x0, FALSE, &id, FALSE);\r
37         }else{\r
38                 rgb->bus_info.spi->ops->spi_send_cmd(0x0);\r
39                 rgb->bus_info.spi->ops->spi_read(&id);\r
40         }\r
41 \r
42         return id;\r
43 }\r
44 \r
45 static void rgb_dispc_init_config(struct panel_spec *panel)\r
46 {\r
47         uint32_t reg_val = 0;\r
48 \r
49         FB_PRINT("sprdfb: [%s]\n", __FUNCTION__);\r
50 \r
51         if(NULL == panel){\r
52                 FB_PRINT("sprdfb: [%s] fail.(Invalid Param)\n", __FUNCTION__);\r
53                 return;\r
54         }\r
55 \r
56         if(SPRDFB_PANEL_TYPE_RGB != panel->type){\r
57                 FB_PRINT("sprdfb: [%s] fail.(not  rgb panel)\n", __FUNCTION__);\r
58                 return;\r
59         }\r
60 \r
61         /*use dpi as interface*/\r
62         dispc_clear_bits((3<<1), DISPC_CTRL);\r
63 \r
64         /*h sync pol*/\r
65         if(SPRDFB_POLARITY_NEG == panel->info.rgb->h_sync_pol){\r
66                 reg_val |= (1<<0);\r
67         }\r
68 \r
69         /*v sync pol*/\r
70         if(SPRDFB_POLARITY_NEG == panel->info.rgb->v_sync_pol){\r
71                 reg_val |= (1<<1);\r
72         }\r
73 \r
74         /*de sync pol*/\r
75         if(SPRDFB_POLARITY_NEG == panel->info.rgb->de_pol){\r
76                 reg_val |= (1<<2);\r
77         }\r
78 \r
79         /*always run mode*/\r
80         reg_val &= ~ (1<<3);\r
81 \r
82         /*dpi bits*/\r
83         switch(panel->info.rgb->video_bus_width){\r
84         case 16:\r
85                 break;\r
86         case 18:\r
87                 reg_val |= (1 << 6);\r
88                 break;\r
89         case 24:\r
90                 reg_val |= (2 << 6);\r
91                 break;\r
92         default:\r
93                 break;\r
94         }\r
95 \r
96         dispc_write(reg_val, DISPC_DPI_CTRL);\r
97 \r
98         FB_PRINT("sprdfb: [%s] DISPC_DPI_CTRL = %d\n", __FUNCTION__, dispc_read(DISPC_DPI_CTRL));\r
99 }\r
100 \r
101 static void rgb_dispc_set_timing(struct sprdfb_device *dev)\r
102 {\r
103         FB_PRINT("sprdfb: [%s]\n", __FUNCTION__);\r
104 \r
105         dispc_write(dev->panel_timing.rgb_timing[RGB_LCD_H_TIMING], DISPC_DPI_H_TIMING);\r
106         dispc_write(dev->panel_timing.rgb_timing[RGB_LCD_V_TIMING], DISPC_DPI_V_TIMING);\r
107 }\r
108 \r
109 uint32_t rgb_calc_h_timing(struct timing_rgb *timing)\r
110 {\r
111 #if 0\r
112         uint32_t  clk_rate;\r
113         uint32_t  hsync, hbp, hfp;\r
114 //      struct clk * clk = NULL;\r
115 \r
116         if(NULL == timing){\r
117                 FB_PRINT("sprdfb: [%s]: Invalid Param\n", __FUNCTION__);\r
118                 return 0;\r
119         }\r
120 \r
121 //      clk_get(NULL,"clk_dispc_dpi");\r
122 //      clk_rate = clk_get_rate(clk) / 1000000;\r
123         clk_rate = 250; // 250 MHz\r
124 \r
125         FB_PRINT("sprdfb: [%s] clk_rate: 0x%x\n", __FUNCTION__, clk_rate);\r
126 \r
127 /********************************************************\r
128         * we assume : t = ? ns, dispc_dpi = ? MHz   so\r
129         *      1ns need cycle  :  dispc_dpi /1000\r
130         *      tns need cycles :  t * dispc_dpi / 1000\r
131         *\r
132         ********************************************************/\r
133 #define MAX_DPI_HSYNC_TIMING_VALUE      255\r
134 #define MAX_DPI_HBP_TIMING_VALUE        4095\r
135 #define MAX_DPI_HFP_TIMING_VALUE        4095\r
136 #define DPI_CYCLES(ns) (( (ns) * clk_rate + 1000 - 1)/ 1000)\r
137 \r
138         /* ceiling*/\r
139         hsync = DPI_CYCLES(timing->hsync);\r
140         if (hsync > MAX_DPI_HSYNC_TIMING_VALUE) {\r
141                 hsync = MAX_DPI_HSYNC_TIMING_VALUE ;\r
142         }\r
143 \r
144         hbp = DPI_CYCLES(timing->hbp);\r
145         if (hbp > MAX_DPI_HSYNC_TIMING_VALUE) {\r
146                 hbp = MAX_DPI_HSYNC_TIMING_VALUE ;\r
147         }\r
148 \r
149         hfp = DPI_CYCLES (timing->hfp);\r
150         if (hfp > MAX_DPI_HFP_TIMING_VALUE) {\r
151                 hfp = MAX_DPI_HFP_TIMING_VALUE ;\r
152         }\r
153 \r
154         return (hsync | (hbp << 8) | (hfp << 20));\r
155 #else\r
156         return  (timing->hsync | (timing->hbp << 8) | (timing->hfp << 20));\r
157 #endif\r
158 }\r
159 \r
160 \r
161 uint32_t rgb_calc_v_timing(struct timing_rgb *timing)\r
162 {\r
163         return (timing->vsync| (timing->vbp << 8) | (timing->vfp << 20));\r
164 }\r
165 \r
166 static int32_t sprdfb_rgb_panel_check(struct panel_spec *panel)\r
167 {\r
168         if(NULL == panel){\r
169                 FB_PRINT("sprdfb: [%s] fail. (Invalid param)\n", __FUNCTION__);\r
170                 return 0;\r
171         }\r
172 \r
173         if(SPRDFB_PANEL_TYPE_RGB != panel->type){\r
174                 FB_PRINT("sprdfb: [%s] fail. (not rgb param)\n", __FUNCTION__);\r
175                 return 0;\r
176         }\r
177 \r
178         FB_PRINT("sprdfb: [%s]\n",__FUNCTION__);\r
179 \r
180         return 1;\r
181 }\r
182 \r
183 static void sprdfb_rgb_panel_mount(struct sprdfb_device *dev)\r
184 {\r
185         if((NULL == dev) || (NULL == dev->panel)){\r
186                 FB_PRINT("sprdfb: [%s]: Invalid Param\n", __FUNCTION__);\r
187                 return;\r
188         }\r
189 \r
190         FB_PRINT("sprdfb: [%s]\n",__FUNCTION__);\r
191 \r
192         dev->panel_if_type = SPRDFB_PANEL_IF_DPI;\r
193 \r
194         if(SPRDFB_RGB_BUS_TYPE_I2C == dev->panel->info.rgb->cmd_bus_mode){\r
195                 dev->panel->info.rgb->bus_info.i2c->ops = &sprdfb_i2c_ops;\r
196         }else{\r
197                 dev->panel->info.rgb->bus_info.spi->ops = &sprdfb_spi_ops;\r
198         }\r
199 \r
200         if(NULL == dev->panel->ops->panel_readid){\r
201                 dev->panel->ops->panel_readid = rgb_readid;\r
202         }\r
203 \r
204         dev->panel_timing.rgb_timing[RGB_LCD_H_TIMING] = rgb_calc_h_timing(dev->panel->info.rgb->timing);\r
205         dev->panel_timing.rgb_timing[RGB_LCD_V_TIMING] = rgb_calc_v_timing(dev->panel->info.rgb->timing);\r
206 }\r
207 \r
208 static void sprdfb_rgb_panel_init(struct sprdfb_device *dev)\r
209 {\r
210         if(SPRDFB_RGB_BUS_TYPE_I2C == dev->panel->info.rgb->cmd_bus_mode){\r
211                 sprdfb_i2c_init(dev);\r
212         }else if(SPRDFB_RGB_BUS_TYPE_SPI == dev->panel->info.rgb->cmd_bus_mode) {\r
213                 sprdfb_spi_init(dev);\r
214         }\r
215                 \r
216         rgb_dispc_init_config(dev->panel);\r
217         rgb_dispc_set_timing(dev);\r
218 \r
219         dispc_set_bits((1 << 4), DISPC_CTRL);   //rgb panel need to out put clock before init\r
220         udelay(1200);\r
221         dispc_clear_bits((1 << 4), DISPC_CTRL); \r
222 }\r
223 \r
224 static void sprdfb_rgb_panel_uninit(struct sprdfb_device *dev)\r
225 {\r
226         if(SPRDFB_RGB_BUS_TYPE_I2C == dev->panel->info.rgb->cmd_bus_mode){\r
227                 sprdfb_i2c_uninit(dev);\r
228         }else if(SPRDFB_RGB_BUS_TYPE_SPI == dev->panel->info.rgb->cmd_bus_mode) {\r
229                 sprdfb_spi_uninit(dev);\r
230         }\r
231 }\r
232 \r
233 struct panel_if_ctrl sprdfb_rgb_ctrl = {\r
234         .if_name                = "rgb",\r
235         .panel_if_check         = sprdfb_rgb_panel_check,\r
236         .panel_if_mount                 = sprdfb_rgb_panel_mount,\r
237         .panel_if_init          = sprdfb_rgb_panel_init,\r
238         .panel_if_uninit                = sprdfb_rgb_panel_uninit,\r
239         .panel_if_before_refresh        = NULL,\r
240         .panel_if_after_refresh = NULL,\r
241 };\r
242 \r
243 \r