13
#include <drivers/video/fb.h>
14
#include <embox/unit.h>
15
#include <kernel/irq.h>
20
#define IPU_MAX_WIDTH OPTION_GET(NUMBER, xres)
21
#define IPU_MAX_HEIGHT OPTION_GET(NUMBER, yres)
24
#define UPPER_MARGIN OPTION_GET(NUMBER, upper_margin)
25
#define LOWER_MARGIN OPTION_GET(NUMBER, lower_margin)
26
#define LEFT_MARGIN OPTION_GET(NUMBER, left_margin)
27
#define RIGHT_MARGIN OPTION_GET(NUMBER, right_margin)
28
#define VSYNC_LEN OPTION_GET(NUMBER, vsync_len)
29
#define HSYNC_LEN OPTION_GET(NUMBER, hsync_len)
31
static uint16_t ipu_fb[IPU_MAX_WIDTH * IPU_MAX_HEIGHT]
32
__attribute__ ((aligned (0x8)));
43
static struct mxcfb_info mxc_fbi;
45
static int mxcfb_set_par(struct fb_info *fbi, const struct fb_var_screeninfo *var) {
46
if (mxc_fbi.ipu_ch != MEM_BG_SYNC)
49
ipu_disable_channel(mxc_fbi.ipu, mxc_fbi.ipu_ch, 0);
50
ipu_uninit_channel(mxc_fbi.ipu, mxc_fbi.ipu_ch);
52
fbi->screen_base = (void*) ipu_fb;
53
fbi->screen_size = IPU_MAX_WIDTH * IPU_MAX_HEIGHT * 2;
55
memset((char *)fbi->screen_base, 0x00, fbi->screen_size);
57
ipu_init_channel(mxc_fbi.ipu, mxc_fbi.ipu_ch, 0);
59
fbi->var = (struct fb_var_screeninfo) {
60
.xres = IPU_MAX_WIDTH,
61
.yres = IPU_MAX_HEIGHT,
63
.upper_margin = UPPER_MARGIN,
64
.lower_margin = LOWER_MARGIN,
65
.left_margin = LEFT_MARGIN,
66
.right_margin = RIGHT_MARGIN,
67
.hsync_len = HSYNC_LEN,
68
.vsync_len = VSYNC_LEN,
71
ipu_init_sync_panel(mxc_fbi.ipu, mxc_fbi.ipu_di,
75
ipu_init_channel_buffer(mxc_fbi.ipu,
76
mxc_fbi.ipu_ch, IPU_INPUT_BUFFER,
78
fbi->var.xres, fbi->var.yres,
79
fbi->var.xres * fbi->var.bits_per_pixel / 8,
80
(dma_addr_t) fbi->screen_base);
82
ipu_enable_channel(mxc_fbi.ipu, mxc_fbi.ipu_ch);
87
static int mxcfb_set_base(struct fb_info *fbi, void *new_base) {
88
ipu_init_channel_buffer(mxc_fbi.ipu,
89
mxc_fbi.ipu_ch, IPU_INPUT_BUFFER,
91
fbi->var.xres, fbi->var.yres,
92
fbi->var.xres * fbi->var.bits_per_pixel / 8,
97
static struct fb_ops mxcfb_ops = {
98
.fb_set_var = mxcfb_set_par,
99
.fb_set_base = mxcfb_set_base,
102
static irq_return_t mxcfb_irq_handler(unsigned int irq, void *data) {
103
struct ipu_soc *ipu = mxc_fbi.ipu;
105
uint32_t int_stat, int_ctrl;
106
const int int_reg[] = { 1, 2, 3, 4, 11, 12, 13, 14, 15, 0 };
108
dcache_flush(ipu_fb, sizeof(ipu_fb) * 2);
110
for (i = 0; int_reg[i] != 0; i++) {
111
int_stat = ipu_cm_read(ipu, IPU_INT_STAT(int_reg[i]));
112
int_ctrl = ipu_cm_read(ipu, IPU_INT_CTRL(int_reg[i]));
113
int_stat &= int_ctrl;
114
ipu_cm_write(ipu, int_stat, IPU_INT_STAT(int_reg[i]));
120
static int ipu_init(void) {
123
mxc_fbi.fbi = fb_create(&mxcfb_ops,
125
2 * IPU_MAX_WIDTH * IPU_MAX_HEIGHT);
126
mxc_fbi.ipu = ipu_get();
127
mxc_fbi.ipu_ch = MEM_BG_SYNC;
129
irq_attach(IPU1_SYNC_IRQ, mxcfb_irq_handler, 0, NULL, "IPU framebuffer");
130
ipu_request_irq(ipu_get(), 23, 0, "", NULL);
132
mxcfb_set_par(mxc_fbi.fbi, &mxc_fbi.fbi->var);
136
EMBOX_UNIT_INIT(ipu_init);