Skip to content

Commit

Permalink
[sun4i] port lcd, g2d driver
Browse files Browse the repository at this point in the history
  • Loading branch information
Benn Huang committed Nov 15, 2011
1 parent a96c9d1 commit 22f2ec0
Show file tree
Hide file tree
Showing 116 changed files with 54,223 additions and 1 deletion.
2 changes: 1 addition & 1 deletion drivers/Makefile
Expand Up @@ -120,6 +120,6 @@ obj-$(CONFIG_STAGING) += staging/
obj-y += platform/
obj-y += ieee802154/
#common clk code
obj-y += clk/
#obj-y += clk/

obj-$(CONFIG_HWSPINLOCK) += hwspinlock/
2 changes: 2 additions & 0 deletions drivers/char/Kconfig
Expand Up @@ -633,5 +633,7 @@ config MSM_SMD_PKT
Enables userspace clients to read and write to some packet SMD
ports via device interface for MSM chipset.

source "drivers/char/sun4i_g2d/Kconfig"

endmenu

1 change: 1 addition & 0 deletions drivers/char/Makefile
Expand Up @@ -63,4 +63,5 @@ obj-$(CONFIG_PS3_FLASH) += ps3flash.o
obj-$(CONFIG_RAMOOPS) += ramoops.o

obj-$(CONFIG_JS_RTC) += js-rtc.o
obj-$(CONFIG_SUN4I_G2D) += sun4i_g2d/
js-rtc-y = rtc.o
8 changes: 8 additions & 0 deletions drivers/char/sun4i_g2d/Kconfig
@@ -0,0 +1,8 @@

config SUN4I_G2D
tristate "SUN4I G2D"
default y
# depends on HAS_IOMEM
help


7 changes: 7 additions & 0 deletions drivers/char/sun4i_g2d/Makefile
@@ -0,0 +1,7 @@
#
# Makefile for the kernel mixer device drivers.
#

obj-$(CONFIG_SUN4I_G2D) += g2d_23.o

g2d_23-objs := g2d_driver.o g2d.o g2d_bsp.o
298 changes: 298 additions & 0 deletions drivers/char/sun4i_g2d/g2d.c
@@ -0,0 +1,298 @@
#include "g2d.h"
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <mach/clock.h>
#include "g2d_driver_i.h"

struct clk *g2d_ahbclk,*g2d_dramclk,*g2d_mclk,*g2d_src;
extern __g2d_drv_t g2d_ext_hd;

int g2d_openclk(void)
{
__u32 ret;

/* ahb g2d gating */
g2d_ahbclk = clk_get(NULL,"ahb_de_mix");

/* sdram g2d gating */
g2d_dramclk = clk_get(NULL,"sdram_de_mix");

/* g2d gating */
g2d_mclk = clk_get(NULL,"de_mix");

/*disable mp clk reset*/
clk_reset(g2d_mclk,0);

/* set g2d clk value */
g2d_src = clk_get(NULL,"sdram_pll_p");//video_pll0
ret = clk_set_parent(g2d_mclk, g2d_src);
clk_put(g2d_src);

ret = clk_get_rate(g2d_src);
clk_set_rate(g2d_mclk,ret/2);

return 0;
}

int g2d_closeclk(void)/* used once when g2d driver exit */
{
clk_disable(g2d_ahbclk);
clk_disable(g2d_dramclk);
clk_disable(g2d_mclk);

clk_put(g2d_ahbclk);
clk_put(g2d_dramclk);
clk_put(g2d_mclk);

return 0;
}

int g2d_clk_on(void)/* used in request */
{
clk_enable(g2d_ahbclk);
clk_enable(g2d_dramclk);
clk_enable(g2d_mclk);

return 0;
}

int g2d_clk_off(void)/* used in release */
{
clk_disable(g2d_ahbclk);
clk_disable(g2d_dramclk);
clk_disable(g2d_mclk);

return 0;
}

irqreturn_t g2d_handle_irq(int irq, void *dev_id)
{
__u32 irq_flag;

irq_flag = mixer_get_irq();
if(irq_flag & G2D_FINISH_IRQ)
{
mixer_clear_init();
g2d_ext_hd.finish_flag = 1;
wake_up(&g2d_ext_hd.queue);
}

return IRQ_HANDLED;
}

int g2d_init(g2d_init_para *para)
{
mixer_set_reg_base(para->g2d_base);

return 0;
}

int g2d_exit(void)
{
__u8 err = 0;
g2d_closeclk();

return err;
}

int g2d_wait_cmd_finish(void)
{
long timeout = 50; /* 30ms */

timeout = wait_event_timeout(g2d_ext_hd.queue, g2d_ext_hd.finish_flag == 1, msecs_to_jiffies(timeout));
if(timeout == 0)
{
mixer_clear_init();
printk("wait g2d irq pending flag timeout\n");
g2d_ext_hd.finish_flag = 1;
wake_up(&g2d_ext_hd.queue);
return -1;
}
return 0;
}

int g2d_blit(g2d_blt * para)
{
__s32 err = 0;

/* check the parameter valid */
if(((para->src_rect.x < 0)&&((-para->src_rect.x) > para->src_rect.w)) ||
((para->src_rect.y < 0)&&((-para->src_rect.y) > para->src_rect.h)) ||
((para->dst_x < 0)&&((-para->dst_x) > para->src_rect.w)) ||
((para->dst_y < 0)&&((-para->dst_y) > para->src_rect.h)) ||
((para->src_rect.x > 0)&&(para->src_rect.x > para->src_image.w - 1)) ||
((para->src_rect.y > 0)&&(para->src_rect.y > para->src_image.h - 1)) ||
((para->dst_x > 0)&&(para->dst_x > para->dst_image.w - 1)) ||
((para->dst_y > 0)&&(para->dst_y > para->dst_image.h - 1)))
{
printk("invalid blit parameter setting");
return -EINVAL;
}
else
{
if(((para->src_rect.x < 0)&&((-para->src_rect.x) < para->src_rect.w)))
{
para->src_rect.w = para->src_rect.w + para->src_rect.x;
para->src_rect.x = 0;
}
else if((para->src_rect.x + para->src_rect.w) > para->src_image.w)
{
para->src_rect.w = para->src_image.w - para->src_rect.x;
}
if(((para->src_rect.y < 0)&&((-para->src_rect.y) < para->src_rect.h)))
{
para->src_rect.h = para->src_rect.h + para->src_rect.y;
para->src_rect.y = 0;
}
else if((para->src_rect.y + para->src_rect.h) > para->src_image.h)
{
para->src_rect.h = para->src_image.h - para->src_rect.y;
}

if(((para->dst_x < 0)&&((-para->dst_x) < para->src_rect.w)))
{
para->src_rect.w = para->src_rect.w + para->dst_x;
para->src_rect.x = (-para->dst_x);
para->dst_x = 0;
}
else if((para->dst_x + para->src_rect.w) > para->dst_image.w)
{
para->src_rect.w = para->dst_image.w - para->dst_x;
}
if(((para->dst_y < 0)&&((-para->dst_y) < para->src_rect.h)))
{
para->src_rect.h = para->src_rect.h + para->dst_y;
para->src_rect.y = (-para->dst_y);
para->dst_y = 0;
}
else if((para->dst_y + para->src_rect.h) > para->dst_image.h)
{
para->src_rect.h = para->dst_image.h - para->dst_y;
}
}

g2d_ext_hd.finish_flag = 0;
err = mixer_blt(para);

return err;
}

int g2d_fill(g2d_fillrect * para)
{
__s32 err = 0;

/* check the parameter valid */
if(((para->dst_rect.x < 0)&&((-para->dst_rect.x)>para->dst_rect.w)) ||
((para->dst_rect.y < 0)&&((-para->dst_rect.y)>para->dst_rect.h)) ||
((para->dst_rect.x > 0)&&(para->dst_rect.x > para->dst_image.w - 1)) ||
((para->dst_rect.y > 0)&&(para->dst_rect.y > para->dst_image.h - 1)))
{
printk("invalid fillrect parameter setting");
return -EINVAL;
}
else
{
if(((para->dst_rect.x < 0)&&((-para->dst_rect.x) < para->dst_rect.w)))
{
para->dst_rect.w = para->dst_rect.w + para->dst_rect.x;
para->dst_rect.x = 0;
}
else if((para->dst_rect.x + para->dst_rect.w) > para->dst_image.w)
{
para->dst_rect.w = para->dst_image.w - para->dst_rect.x;
}
if(((para->dst_rect.y < 0)&&((-para->dst_rect.y) < para->dst_rect.h)))
{
para->dst_rect.h = para->dst_rect.h + para->dst_rect.y;
para->dst_rect.y = 0;
}
else if((para->dst_rect.y + para->dst_rect.h) > para->dst_image.h)
{
para->dst_rect.h = para->dst_image.h - para->dst_rect.y;
}
}

g2d_ext_hd.finish_flag = 0;
err = mixer_fillrectangle(para);

return err;
}

int g2d_stretchblit(g2d_stretchblt * para)
{
__s32 err = 0;

/* check the parameter valid */
if(((para->src_rect.x < 0)&&((-para->src_rect.x) > para->src_rect.w)) ||
((para->src_rect.y < 0)&&((-para->src_rect.y) > para->src_rect.h)) ||
((para->dst_rect.x < 0)&&((-para->dst_rect.x) > para->dst_rect.w)) ||
((para->dst_rect.y < 0)&&((-para->dst_rect.y) > para->dst_rect.h)) ||
((para->src_rect.x > 0)&&(para->src_rect.x > para->src_image.w - 1)) ||
((para->src_rect.y > 0)&&(para->src_rect.y > para->src_image.h - 1)) ||
((para->dst_rect.x > 0)&&(para->dst_rect.x > para->dst_image.w - 1)) ||
((para->dst_rect.y > 0)&&(para->dst_rect.y > para->dst_image.h - 1)))
{
printk("invalid stretchblit parameter setting");
return -EINVAL;
}
else
{
if(((para->src_rect.x < 0)&&((-para->src_rect.x) < para->src_rect.w)))
{
para->src_rect.w = para->src_rect.w + para->src_rect.x;
para->src_rect.x = 0;
}
else if((para->src_rect.x + para->src_rect.w) > para->src_image.w)
{
para->src_rect.w = para->src_image.w - para->src_rect.x;
}
if(((para->src_rect.y < 0)&&((-para->src_rect.y) < para->src_rect.h)))
{
para->src_rect.h = para->src_rect.h + para->src_rect.y;
para->src_rect.y = 0;
}
else if((para->src_rect.y + para->src_rect.h) > para->src_image.h)
{
para->src_rect.h = para->src_image.h - para->src_rect.y;
}

if(((para->dst_rect.x < 0)&&((-para->dst_rect.x) < para->dst_rect.w)))
{
para->dst_rect.w = para->dst_rect.w + para->dst_rect.x;
para->dst_rect.x = 0;
}
else if((para->dst_rect.x + para->dst_rect.w) > para->dst_image.w)
{
para->dst_rect.w = para->dst_image.w - para->dst_rect.x;
}
if(((para->dst_rect.y < 0)&&((-para->dst_rect.y) < para->dst_rect.h)))
{
para->dst_rect.h = para->dst_rect.h + para->dst_rect.y;
para->dst_rect.y = 0;
}
else if((para->dst_rect.y + para->dst_rect.h) > para->dst_image.h)
{
para->dst_rect.h = para->dst_image.h - para->dst_rect.y;
}
}

g2d_ext_hd.finish_flag = 0;
err = mixer_stretchblt(para);

return err;
}

int g2d_set_palette_table(g2d_palette *para)
{

if((para->pbuffer == NULL) || (para->size < 0) || (para->size>1024))
{
printk("para invalid in mixer_set_palette\n");
return -1;
}

mixer_set_palette(para);

return 0;
}

29 changes: 29 additions & 0 deletions drivers/char/sun4i_g2d/g2d.h
@@ -0,0 +1,29 @@

#ifndef __G2D_H__
#define __G2D_H__

#include"g2d_bsp.h"

/* Mixer status select */
#define G2D_FINISH_IRQ (1<<8)
#define G2D_ERROR_IRQ (1<<9)

typedef struct
{
g2d_init_para init_para;

}g2d_dev_t;

int g2d_openclk(void);
int g2d_closeclk(void);
int g2d_clk_on(void);
int g2d_clk_off(void);
irqreturn_t g2d_handle_irq(int irq, void *dev_id);
int g2d_init(g2d_init_para *para);
int g2d_blit(g2d_blt * para);
int g2d_fill(g2d_fillrect * para);
int g2d_stretchblit(g2d_stretchblt * para);
int g2d_set_palette_table(g2d_palette *para);
int g2d_wait_cmd_finish(void);

#endif/* __G2D_H__ */

0 comments on commit 22f2ec0

Please sign in to comment.