PageRenderTime 34ms CodeModel.GetById 19ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/char/sun4i_g2d/g2d.c

https://bitbucket.org/ndreys/linux-sunxi
C | 320 lines | 246 code | 45 blank | 29 comment | 41 complexity | 86e1032edbc3c1d43388aad177b6bb99 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1/*
  2 * drivers/char/sun4i_g2d/g2d.c
  3 *
  4 * (C) Copyright 2007-2012
  5 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
  6 *
  7 * This program is free software; you can redistribute it and/or
  8 * modify it under the terms of the GNU General Public License as
  9 * published by the Free Software Foundation; either version 2 of
 10 * the License, or (at your option) any later version.
 11 *
 12 * This program is distributed in the hope that it will be useful,
 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
 15 * GNU General Public License for more details.
 16 *
 17 * You should have received a copy of the GNU General Public License
 18 * along with this program; if not, write to the Free Software
 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 20 * MA 02111-1307 USA
 21 */
 22
 23#include "g2d.h"
 24#include <linux/clk.h>
 25#include <linux/interrupt.h>
 26#include <mach/clock.h>
 27#include "g2d_driver_i.h"
 28
 29struct clk *g2d_ahbclk,*g2d_dramclk,*g2d_mclk,*g2d_src;
 30extern __g2d_drv_t	 g2d_ext_hd;
 31
 32int g2d_openclk(void)
 33{
 34	__u32 ret;
 35	
 36	/* ahb g2d gating */
 37	g2d_ahbclk = clk_get(NULL,"ahb_de_mix");
 38	
 39	/* sdram g2d gating */
 40	g2d_dramclk = clk_get(NULL,"sdram_de_mix");
 41	
 42	/* g2d gating */
 43	g2d_mclk = clk_get(NULL,"de_mix");
 44		
 45	/*disable mp clk reset*/
 46	clk_reset(g2d_mclk,0);
 47	
 48	/* set g2d clk value */
 49	g2d_src = clk_get(NULL,"sdram_pll_p");//video_pll0
 50	ret = clk_set_parent(g2d_mclk, g2d_src);
 51	clk_put(g2d_src);
 52	
 53	ret = clk_get_rate(g2d_src);
 54	clk_set_rate(g2d_mclk,ret/2);
 55		
 56	return 0;
 57}
 58
 59int g2d_closeclk(void)/* used once when g2d driver exit */
 60{	
 61	clk_disable(g2d_ahbclk);
 62	clk_disable(g2d_dramclk);
 63	clk_disable(g2d_mclk);
 64	
 65	clk_put(g2d_ahbclk);
 66	clk_put(g2d_dramclk);
 67	clk_put(g2d_mclk);
 68
 69	return 0;
 70}
 71
 72int g2d_clk_on(void)/* used in request */
 73{	
 74	clk_enable(g2d_ahbclk);
 75	clk_enable(g2d_dramclk);
 76	clk_enable(g2d_mclk);
 77	
 78	return  0;
 79}
 80
 81int g2d_clk_off(void)/* used in release */
 82{
 83	clk_disable(g2d_ahbclk);
 84	clk_disable(g2d_dramclk);
 85	clk_disable(g2d_mclk);
 86	
 87	return  0;
 88}
 89
 90irqreturn_t g2d_handle_irq(int irq, void *dev_id)
 91{
 92    __u32 irq_flag;
 93
 94    irq_flag = mixer_get_irq();
 95    if(irq_flag & G2D_FINISH_IRQ)
 96    {
 97		mixer_clear_init();
 98		g2d_ext_hd.finish_flag = 1;
 99		wake_up(&g2d_ext_hd.queue);	
100    }
101
102    return IRQ_HANDLED;
103}
104
105int g2d_init(g2d_init_para *para)
106{
107	mixer_set_reg_base(para->g2d_base);
108
109	return 0;
110}
111
112int g2d_exit(void)
113{
114	__u8 err = 0;
115	g2d_closeclk();
116	
117	return err;
118}
119
120int g2d_wait_cmd_finish(void)
121{
122	long timeout = 50; /* 30ms */
123	
124	timeout = wait_event_timeout(g2d_ext_hd.queue, g2d_ext_hd.finish_flag == 1, msecs_to_jiffies(timeout));
125	if(timeout == 0)
126	{
127		mixer_clear_init();
128		printk("wait g2d irq pending flag timeout\n");
129		g2d_ext_hd.finish_flag = 1;
130		wake_up(&g2d_ext_hd.queue);
131		return -1;
132	}
133	return 0;
134}
135
136int g2d_blit(g2d_blt * para)
137{
138	__s32 err = 0;
139	
140	/* check the parameter valid */
141    if(((para->src_rect.x < 0)&&((-para->src_rect.x) > para->src_rect.w)) ||
142       ((para->src_rect.y < 0)&&((-para->src_rect.y) > para->src_rect.h)) ||
143       ((para->dst_x < 0)&&((-para->dst_x) > para->src_rect.w)) ||
144       ((para->dst_y < 0)&&((-para->dst_y) > para->src_rect.h)) ||
145       ((para->src_rect.x > 0)&&(para->src_rect.x > para->src_image.w - 1)) ||
146       ((para->src_rect.y > 0)&&(para->src_rect.y > para->src_image.h - 1)) ||
147       ((para->dst_x > 0)&&(para->dst_x > para->dst_image.w - 1)) ||
148       ((para->dst_y > 0)&&(para->dst_y > para->dst_image.h - 1)))
149	{
150		printk("invalid blit parameter setting");
151		return -EINVAL;
152	}
153	else
154	{
155		if(((para->src_rect.x < 0)&&((-para->src_rect.x) < para->src_rect.w)))
156		{
157			para->src_rect.w = para->src_rect.w + para->src_rect.x;
158			para->src_rect.x = 0;
159		}
160		else if((para->src_rect.x + para->src_rect.w) > para->src_image.w)
161		{
162			para->src_rect.w = para->src_image.w - para->src_rect.x;
163		}	
164		if(((para->src_rect.y < 0)&&((-para->src_rect.y) < para->src_rect.h)))
165		{
166			para->src_rect.h = para->src_rect.h + para->src_rect.y;
167			para->src_rect.y = 0;
168		}
169		else if((para->src_rect.y + para->src_rect.h) > para->src_image.h)
170		{
171			para->src_rect.h = para->src_image.h - para->src_rect.y;
172		}
173		
174		if(((para->dst_x < 0)&&((-para->dst_x) < para->src_rect.w)))
175		{
176			para->src_rect.w = para->src_rect.w + para->dst_x;
177			para->src_rect.x = (-para->dst_x);
178			para->dst_x = 0;
179		}	
180		else if((para->dst_x + para->src_rect.w) > para->dst_image.w)
181		{
182			para->src_rect.w = para->dst_image.w - para->dst_x;
183		}
184		if(((para->dst_y < 0)&&((-para->dst_y) < para->src_rect.h)))
185		{
186			para->src_rect.h = para->src_rect.h + para->dst_y;
187			para->src_rect.y = (-para->dst_y);
188			para->dst_y = 0;
189		}
190		else if((para->dst_y + para->src_rect.h) > para->dst_image.h)
191		{
192			para->src_rect.h = para->dst_image.h - para->dst_y;
193		}
194	}
195	
196	g2d_ext_hd.finish_flag = 0;
197	err = mixer_blt(para);
198   	
199	return err;
200}
201
202int g2d_fill(g2d_fillrect * para)
203{
204	__s32 err = 0;
205	
206	/* check the parameter valid */
207	if(((para->dst_rect.x < 0)&&((-para->dst_rect.x)>para->dst_rect.w)) ||
208	   ((para->dst_rect.y < 0)&&((-para->dst_rect.y)>para->dst_rect.h)) ||
209	   ((para->dst_rect.x > 0)&&(para->dst_rect.x > para->dst_image.w - 1)) ||
210	   ((para->dst_rect.y > 0)&&(para->dst_rect.y > para->dst_image.h - 1)))
211	{
212		printk("invalid fillrect parameter setting");
213		return -EINVAL;
214	}
215	else
216	{
217		if(((para->dst_rect.x < 0)&&((-para->dst_rect.x) < para->dst_rect.w)))
218		{
219			para->dst_rect.w = para->dst_rect.w + para->dst_rect.x;
220			para->dst_rect.x = 0;			
221		}
222		else if((para->dst_rect.x + para->dst_rect.w) > para->dst_image.w)
223		{
224			para->dst_rect.w = para->dst_image.w - para->dst_rect.x;
225		}	
226		if(((para->dst_rect.y < 0)&&((-para->dst_rect.y) < para->dst_rect.h)))
227		{
228			para->dst_rect.h = para->dst_rect.h + para->dst_rect.y;
229			para->dst_rect.y = 0;			
230		}
231		else if((para->dst_rect.y + para->dst_rect.h) > para->dst_image.h)
232		{
233			para->dst_rect.h = para->dst_image.h - para->dst_rect.y;
234		}		
235	}
236	
237	g2d_ext_hd.finish_flag = 0;
238	err = mixer_fillrectangle(para);
239
240	return err;
241}
242
243int g2d_stretchblit(g2d_stretchblt * para)
244{
245	__s32 err = 0;
246
247	/* check the parameter valid */
248    if(((para->src_rect.x < 0)&&((-para->src_rect.x) > para->src_rect.w)) ||
249       ((para->src_rect.y < 0)&&((-para->src_rect.y) > para->src_rect.h)) ||
250       ((para->dst_rect.x < 0)&&((-para->dst_rect.x) > para->dst_rect.w)) ||
251       ((para->dst_rect.y < 0)&&((-para->dst_rect.y) > para->dst_rect.h)) ||
252       ((para->src_rect.x > 0)&&(para->src_rect.x > para->src_image.w - 1)) ||
253       ((para->src_rect.y > 0)&&(para->src_rect.y > para->src_image.h - 1)) ||
254       ((para->dst_rect.x > 0)&&(para->dst_rect.x > para->dst_image.w - 1)) ||
255       ((para->dst_rect.y > 0)&&(para->dst_rect.y > para->dst_image.h - 1)))
256	{
257		printk("invalid stretchblit parameter setting");
258		return -EINVAL;
259	}
260	else
261	{
262		if(((para->src_rect.x < 0)&&((-para->src_rect.x) < para->src_rect.w)))
263		{
264			para->src_rect.w = para->src_rect.w + para->src_rect.x;
265			para->src_rect.x = 0;
266		}
267		else if((para->src_rect.x + para->src_rect.w) > para->src_image.w)
268		{
269			para->src_rect.w = para->src_image.w - para->src_rect.x;
270		}	
271		if(((para->src_rect.y < 0)&&((-para->src_rect.y) < para->src_rect.h)))
272		{
273			para->src_rect.h = para->src_rect.h + para->src_rect.y;
274			para->src_rect.y = 0;
275		}
276		else if((para->src_rect.y + para->src_rect.h) > para->src_image.h)
277		{
278			para->src_rect.h = para->src_image.h - para->src_rect.y;
279		}
280		
281		if(((para->dst_rect.x < 0)&&((-para->dst_rect.x) < para->dst_rect.w)))
282		{
283			para->dst_rect.w = para->dst_rect.w + para->dst_rect.x;
284			para->dst_rect.x = 0;
285		}	
286		else if((para->dst_rect.x + para->dst_rect.w) > para->dst_image.w)
287		{
288			para->dst_rect.w = para->dst_image.w - para->dst_rect.x;
289		}
290		if(((para->dst_rect.y < 0)&&((-para->dst_rect.y) < para->dst_rect.h)))
291		{
292			para->dst_rect.h = para->dst_rect.h + para->dst_rect.y;
293			para->dst_rect.y = 0;
294		}
295		else if((para->dst_rect.y + para->dst_rect.h) > para->dst_image.h)
296		{
297			para->dst_rect.h = para->dst_image.h - para->dst_rect.y;
298		}
299	}
300
301	g2d_ext_hd.finish_flag = 0;
302	err = mixer_stretchblt(para);
303   	
304	return err;
305}
306
307int g2d_set_palette_table(g2d_palette *para)
308{
309		
310    if((para->pbuffer == NULL) || (para->size < 0) || (para->size>1024))
311    {
312        printk("para invalid in mixer_set_palette\n");
313        return -1;
314    }
315	
316	mixer_set_palette(para);
317
318	return 0;
319}
320