tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / media / sprd_gsp / gsp_config_if.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 \r
14 /**---------------------------------------------------------------------------*\r
15 **                         Dependencies                                      *\r
16 **---------------------------------------------------------------------------*/\r
17 //#include <linux/irq.h>\r
18 \r
19 \r
20 #include "gsp_config_if.h"\r
21 \r
22 \r
23 \r
24 /**---------------------------------------------------------------------------*\r
25  **                         Dependencies                                      *\r
26  **---------------------------------------------------------------------------*/\r
27 \r
28 /**---------------------------------------------------------------------------*\r
29  **                         Macro Definition                                  *\r
30  **---------------------------------------------------------------------------*/\r
31 \r
32 \r
33 /**---------------------------------------------------------------------------*\r
34  **                         Function Define                                   *\r
35  **---------------------------------------------------------------------------*/\r
36 \r
37 LOCAL void GSP_SetLayer0Parameter(gsp_context_t *gspCtx)\r
38 {\r
39     if(!gspCtx->gsp_cfg.layer0_info.layer_en) {\r
40         GSP_L0_ENABLE_SET(0);\r
41         return ;\r
42     }\r
43 \r
44     GSP_L0_ADDR_SET(gspCtx->gsp_cfg.layer0_info.src_addr);\r
45     GSP_L0_PITCH_SET(gspCtx->gsp_cfg.layer0_info.pitch);\r
46     GSP_L0_CLIPRECT_SET(gspCtx->gsp_cfg.layer0_info.clip_rect);\r
47     GSP_L0_DESRECT_SET(gspCtx->gsp_cfg.layer0_info.des_rect);\r
48     GSP_L0_GREY_SET(gspCtx->gsp_cfg.layer0_info.grey);\r
49     GSP_L0_ENDIAN_SET(gspCtx->gsp_cfg.layer0_info.endian_mode);\r
50     GSP_L0_ALPHA_SET(gspCtx->gsp_cfg.layer0_info.alpha);\r
51     GSP_L0_COLORKEY_SET(gspCtx->gsp_cfg.layer0_info.colorkey);\r
52     GSP_L0_IMGFORMAT_SET(gspCtx->gsp_cfg.layer0_info.img_format);\r
53     GSP_L0_ROTMODE_SET(gspCtx->gsp_cfg.layer0_info.rot_angle);\r
54     GSP_L0_COLORKEYENABLE_SET(gspCtx->gsp_cfg.layer0_info.colorkey_en);\r
55     GSP_L0_PALLETENABLE_SET(gspCtx->gsp_cfg.layer0_info.pallet_en);\r
56     //GSP_L0_SCALETAPMODE_SET(gspCtx->gsp_cfg.layer0_info.row_tap_mode,gspCtx->gsp_cfg.layer0_info.col_tap_mode);\r
57 \r
58 }\r
59 \r
60 \r
61 LOCAL void GSP_SetLayer1Parameter(gsp_context_t *gspCtx)\r
62 {\r
63     if(!gspCtx->gsp_cfg.layer1_info.layer_en) {\r
64         GSP_L1_ENABLE_SET(0);\r
65         return ;\r
66     }\r
67 \r
68     GSP_L1_ADDR_SET(gspCtx->gsp_cfg.layer1_info.src_addr);\r
69     GSP_L1_PITCH_SET(gspCtx->gsp_cfg.layer1_info.pitch);\r
70     GSP_L1_CLIPRECT_SET(gspCtx->gsp_cfg.layer1_info.clip_rect);\r
71     GSP_L1_DESPOS_SET(gspCtx->gsp_cfg.layer1_info.des_pos);\r
72     GSP_L1_GREY_SET(gspCtx->gsp_cfg.layer1_info.grey);\r
73     GSP_L1_ENDIAN_SET(gspCtx->gsp_cfg.layer1_info.endian_mode);\r
74     GSP_L1_ALPHA_SET(gspCtx->gsp_cfg.layer1_info.alpha);\r
75     GSP_L1_COLORKEY_SET(gspCtx->gsp_cfg.layer1_info.colorkey);\r
76     GSP_L1_IMGFORMAT_SET(gspCtx->gsp_cfg.layer1_info.img_format);\r
77     GSP_L1_ROTMODE_SET(gspCtx->gsp_cfg.layer1_info.rot_angle);\r
78     GSP_L1_COLORKEYENABLE_SET(gspCtx->gsp_cfg.layer1_info.colorkey_en);\r
79     GSP_L1_PALLETENABLE_SET(gspCtx->gsp_cfg.layer1_info.pallet_en);\r
80 \r
81 }\r
82 \r
83 \r
84 LOCAL void GSP_SetLayerDesParameter(gsp_context_t *gspCtx)\r
85 {\r
86     if(!gspCtx->gsp_cfg.layer0_info.layer_en && !gspCtx->gsp_cfg.layer1_info.layer_en) {\r
87         return ;\r
88     }\r
89 \r
90     GSP_Ld_ADDR_SET(gspCtx->gsp_cfg.layer_des_info.src_addr);\r
91     GSP_Ld_PITCH_SET(gspCtx->gsp_cfg.layer_des_info.pitch);\r
92     GSP_Ld_ENDIAN_SET(gspCtx->gsp_cfg.layer_des_info.endian_mode);\r
93     GSP_Ld_IMGFORMAT_SET(gspCtx->gsp_cfg.layer_des_info.img_format);\r
94     GSP_Ld_COMPRESSRGB888_SET(gspCtx->gsp_cfg.layer_des_info.compress_r8_en);\r
95 }\r
96 \r
97 LOCAL void GSP_SetMiscParameter(gsp_context_t *gspCtx)\r
98 {\r
99     if(!gspCtx->gsp_cfg.layer0_info.layer_en && !gspCtx->gsp_cfg.layer1_info.layer_en) {\r
100         return ;\r
101     }\r
102 \r
103     GSP_L0_ENABLE_SET(gspCtx->gsp_cfg.layer0_info.layer_en);\r
104     GSP_L1_ENABLE_SET(gspCtx->gsp_cfg.layer1_info.layer_en);\r
105 \r
106     if(gspCtx->gsp_cfg.layer0_info.scaling_en == 1) {\r
107         GSP_SCALESTATUS_RESET();\r
108     }\r
109     GSP_SCALE_ENABLE_SET(gspCtx->gsp_cfg.layer0_info.scaling_en);\r
110 \r
111 \r
112     GSP_PMARGB_ENABLE_SET(gspCtx->gsp_cfg.layer0_info.pmargb_en||gspCtx->gsp_cfg.layer1_info.pmargb_en);\r
113     GSP_L0_PMARGBMODE_SET(gspCtx->gsp_cfg.layer0_info.pmargb_mod);\r
114     GSP_L1_PMARGBMODE_SET(gspCtx->gsp_cfg.layer1_info.pmargb_mod);\r
115     GSP_PAGES_BOARDER_SPLIT_SET(gspCtx->gsp_cfg.misc_info.split_pages);\r
116     GSP_Y2R_OPT_SET(gspCtx->gsp_cfg.misc_info.y2r_opt);\r
117     GSP_DITHER_ENABLE_SET(gspCtx->gsp_cfg.misc_info.dithering_en);\r
118     //GSP_AHB_CLOCK_SET(gspCtx->gsp_cfg.misc_info.ahb_clock);\r
119     GSP_CLOCK_SET(gspCtx->gsp_cfg.misc_info.gsp_clock);\r
120     GSP_EMC_GAP_SET(gspCtx->gsp_cfg.misc_info.gsp_gap);\r
121 }\r
122 \r
123 PUBLIC void GSP_module_enable(gsp_context_t *gspCtx)\r
124 {\r
125     int ret = 0;\r
126     //GSP_HWMODULE_ENABLE();\r
127     if(gspCtx->gsp_clk != NULL) {\r
128         ret = clk_prepare_enable(gspCtx->gsp_clk);\r
129         if(ret) {\r
130             GSP_TRACE(KERN_ERR "%s: enable clock failed!\n",__FUNCTION__);\r
131             return;\r
132         } else {\r
133             pr_debug(KERN_INFO "%s: enable clock ok!\n",__FUNCTION__);\r
134         }\r
135     } else {\r
136         GSP_TRACE(KERN_ERR "%s: gsp_clk not init yet!\n",__FUNCTION__);\r
137     }\r
138 }\r
139 PUBLIC void GSP_module_disable(gsp_context_t *gspCtx)\r
140 {\r
141     if(gspCtx->gsp_clk != NULL) {\r
142         //GSP_HWMODULE_DISABLE();//disable may not use the enable regiter\r
143         clk_disable_unprepare(gspCtx->gsp_clk);\r
144     } else {\r
145         printk(KERN_ERR "%s: gsp_clk not init yet!\n",__FUNCTION__);\r
146     }\r
147 }\r
148 \r
149 /*\r
150 func:GSP_ClocksCheckPhase0\r
151 desc: check all clock except iommu\r
152 */\r
153 PUBLIC int GSP_ClocksCheckPhase0(void)\r
154 {\r
155     int ret = 0;\r
156 \r
157     //check GSP enable\r
158     if(0==(GSP_REG_READ(GSP_MOD_EN)&GSP_MOD_EN_BIT)) {\r
159         printk(KERN_ERR "%s: err: gsp enable is not set!%lx:%08x\n",__FUNCTION__,\r
160                (ulong)GSP_MOD_EN,GSP_REG_READ(GSP_MOD_EN));\r
161         ret++;\r
162     } else {\r
163         if(GSP_WORKSTATUS_GET() != 0) {\r
164             printk(KERN_ERR "%s: err:busy is still on!!!!\n",__FUNCTION__);\r
165             ret++;\r
166         }\r
167     }\r
168 \r
169     //check GSP clock select\r
170     if(GSP_CLK_SEL_BIT_MASK!=(GSP_REG_READ(GSP_CLOCK_BASE)&GSP_CLK_SEL_BIT_MASK)) {\r
171         printk(KERN_INFO "%s: info: gsp clock select is not set to hightest freq!%lx:%08x\n",__FUNCTION__,\r
172                (ulong)GSP_CLOCK_BASE,GSP_REG_READ(GSP_CLOCK_BASE));\r
173     }\r
174 \r
175     //check GSP AUTO_GATE clock\r
176     if(0==(GSP_REG_READ(GSP_AUTO_GATE_ENABLE_BASE)&GSP_AUTO_GATE_ENABLE_BIT)) {\r
177         printk(KERN_ERR "%s: err: gsp auto gate clock is not enable!%lx:%08x\n",__FUNCTION__,\r
178                (ulong)GSP_AUTO_GATE_ENABLE_BASE,GSP_REG_READ(GSP_AUTO_GATE_ENABLE_BASE));\r
179         ret++;\r
180     }\r
181 \r
182     //check GSP EMC clock\r
183     if(0==(GSP_REG_READ(GSP_EMC_MATRIX_BASE)&GSP_EMC_MATRIX_BIT)) {\r
184         printk(KERN_ERR "%s: err: gsp emc clock is not enable!%lx:%08x\n",__FUNCTION__,\r
185                (ulong)GSP_EMC_MATRIX_BASE,GSP_REG_READ(GSP_EMC_MATRIX_BASE));\r
186         ret++;\r
187     }\r
188     return (ret>0)?GSP_KERNEL_CLOCK_ERR:GSP_NO_ERR;\r
189 }\r
190 \r
191 /*\r
192 func:GSP_ClocksCheckPhase1\r
193 desc: check iommu cfg\r
194 */\r
195 PUBLIC int GSP_ClocksCheckPhase1(void)\r
196 {\r
197     int ret = 0;\r
198     uint32_t ctl_val = GSP_REG_READ(GSP_MMU_CTRL_BASE);\r
199     uint32_t addr_y0 = GSP_L0_ADDRY_GET();\r
200     uint32_t addr_uv0 = GSP_L0_ADDRUV_GET();\r
201     uint32_t addr_va0 = GSP_L0_ADDRVA_GET();\r
202     uint32_t addr_y1 = GSP_L1_ADDRY_GET();\r
203     uint32_t addr_uv1 = GSP_L1_ADDRUV_GET();\r
204     uint32_t addr_va1 = GSP_L1_ADDRVA_GET();\r
205     uint32_t addr_yd = GSP_Ld_ADDRY_GET();\r
206     uint32_t addr_uvd = GSP_Ld_ADDRUV_GET();\r
207     uint32_t addr_vad = GSP_Ld_ADDRVA_GET();\r
208 \r
209 #define IOVA_CHECK(addr)    (0x10000000<= (addr) && (addr) < 0x80000000)\r
210 \r
211     //check GSP IOMMU ENABLE\r
212     if(((ctl_val & 0x1)==0 || (ctl_val & 0xF0000000)==0)/*IOMMU be disabled*/\r
213        &&(((GSP_L0_ENABLE_GET() == 1) && (IOVA_CHECK(addr_y0) || IOVA_CHECK(addr_uv0) || IOVA_CHECK(addr_va0)))/*L0 is enabled and use iova*/\r
214           ||((GSP_L1_ENABLE_GET() == 1) && (IOVA_CHECK(addr_y1) || IOVA_CHECK(addr_uv1) || IOVA_CHECK(addr_va1)))/*L1 is enabled and use iova*/\r
215           ||((GSP_L0_ENABLE_GET() == 1 ||GSP_L1_ENABLE_GET() == 1 ) && (IOVA_CHECK(addr_yd) || IOVA_CHECK(addr_uvd) || IOVA_CHECK(addr_vad))))) {\r
216         printk(KERN_ERR "%s: err: gsp iommu is not enable or iova base is null!%lx:%08x\n",__FUNCTION__,\r
217                (ulong)GSP_MMU_CTRL_BASE,GSP_REG_READ(GSP_MMU_CTRL_BASE));\r
218         ret++;\r
219     }\r
220     return (ret>0)?GSP_KERNEL_CLOCK_ERR:GSP_NO_ERR;\r
221 }\r
222 \r
223 \r
224 PUBLIC int GSP_Init(gsp_context_t *gspCtx)\r
225 {\r
226     int ret = 0;\r
227     GSP_module_enable(gspCtx);\r
228     ret = clk_prepare_enable(gspCtx->gsp_emc_clk);\r
229     //GSP_AUTO_GATE_ENABLE();//gsp driver take charge of auto_gate bit instead of pm\r
230     if(ret) {\r
231         printk(KERN_ERR "%s: enable emc clock failed!\n",__FUNCTION__);\r
232         return GSP_KERNEL_CLOCK_ERR;\r
233     } else {\r
234         pr_debug(KERN_INFO "%s: enable emc clock ok!\n",__FUNCTION__);\r
235     }\r
236 \r
237     //GSP_HWMODULE_SOFTRESET();//sharkL bug 350028\r
238     GSP_IRQMODE_SET(GSP_IRQ_MODE_LEVEL);\r
239     ret = GSP_ClocksCheckPhase0();\r
240     return ret;\r
241 }\r
242 PUBLIC void GSP_Deinit(gsp_context_t *gspCtx)\r
243 {\r
244     clk_disable_unprepare(gspCtx->gsp_emc_clk);\r
245     GSP_IRQSTATUS_CLEAR();\r
246     GSP_IRQENABLE_SET(GSP_IRQ_TYPE_DISABLE);\r
247     GSP_module_disable(gspCtx);\r
248 }\r
249 \r
250 PUBLIC void GSP_ConfigLayer(GSP_MODULE_ID_E layer_id, gsp_context_t *gspCtx)\r
251 {\r
252     switch(layer_id) {\r
253         case GSP_MODULE_LAYER0:\r
254             GSP_SetLayer0Parameter(gspCtx);\r
255             break;\r
256 \r
257         case GSP_MODULE_LAYER1:\r
258             GSP_SetLayer1Parameter(gspCtx);\r
259             break;\r
260 \r
261         case GSP_MODULE_DST:\r
262             GSP_SetLayerDesParameter(gspCtx);\r
263             break;\r
264 \r
265         default:\r
266             GSP_SetMiscParameter(gspCtx);\r
267             break;\r
268     }\r
269 }\r
270 \r
271 PUBLIC void GSP_Wait_Finish(void)\r
272 {\r
273     if(GSP_WORKSTATUS_GET() != 0) {\r
274         printk(KERN_ERR "%s: err:busy is still on!!!!\n",__FUNCTION__);\r
275     }\r
276 }\r
277 \r
278 \r
279 PUBLIC uint32_t GSP_Trigger(void)\r
280 {\r
281     int ret = GSP_ClocksCheckPhase1();\r
282     if(ret) {\r
283         return ret;\r
284     }\r
285     if(GSP_ERRFLAG_GET()) {\r
286         //GSP_ASSERT();\r
287         return GSP_ERRCODE_GET();\r
288     }\r
289 \r
290     GSP_IRQENABLE_SET(GSP_IRQ_TYPE_ENABLE);\r
291     GSP_ENGINE_TRIGGER();\r
292     return 0;\r
293 }\r
294 \r