SmartAudio/lichee/linux-4.9/drivers/char/sunxi_g2d/g2d_bsp_sun8iw11.c

1908 lines
54 KiB
C

/* g2d_bsp.c
*
* Copyright (c) 2011 Allwinnertech Co., Ltd.
* 2011 Yupu Tang
*
* G2D driver
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*/
#include "g2d_regs.h"
#include "g2d_bsp.h"
static unsigned long base_addr;
/* byte input */
#define read_bvalue(offset) get_bvalue(base_addr + offset)
/* byte output */
#define write_bvalue(offset, value) put_bvalue(base_addr + offset, value)
/* half word input */
#define read_hvalue(offset) get_hvalue(base_addr + offset)
/* half word output */
#define write_hvalue(offset, value) put_hvalue(base_addr + offset, value)
/* word input */
#define read_wvalue(offset) get_wvalue(base_addr + offset)
/* word output */
#define write_wvalue(offset, value) put_wvalue(base_addr + offset, value)
__s32 csc0coeff[12] = {
0x4a7, 0x1e6f, 0x1cbf, 0x877,
0x4a7, 0x00, 0x662, 0x3211,
0x4a7, 0x812, 0x00, 0x2eb1
};
__s32 csc1coeff[12] = {
0x4a7, 0x1e6f, 0x1cbf, 0x877,
0x4a7, 0x00, 0x662, 0x3211,
0x4a7, 0x812, 0x00, 0x2eb1
};
__s32 csc2coeff[12] = {
0x204, 0x107, 0x64, 0x100, /* YG,YR,YB,YC */
0x1ED6, 0x1F69, 0x1C1, 0x800, /* UG,UR,UB,UC */
0x1E87, 0x1C1, 0x1FB8, 0x800, /* VG,VR,VB,VC */
};
__s32 csc2coeff_VUVU[12] = {
0x204, 0x107, 0x64, 0x100, /* YG,YR,YB,YC */
0x1E87, 0x1C1, 0x1FB8, 0x800, /* VG,VR,VB,VC */
0x1ED6, 0x1F69, 0x1C1, 0x800, /* UG,UR,UB,UC */
};
__s32 scalercoeff[64] = {
/* Horizontal Filtering Coefficient(0x200-0x27c) */
0x00004000, 0x000140ff, 0x00033ffe, 0x00043ffd, 0x00063efc,
0xff083dfc, 0x000a3bfb, 0xff0d39fb, 0xff0f37fb, 0xff1136fa,
0xfe1433fb, 0xfe1631fb, 0xfd192ffb, 0xfd1c2cfb, 0xfd1f29fb,
0xfc2127fc, 0xfc2424fc, 0xfc2721fc, 0xfb291ffd, 0xfb2c1cfd,
0xfb2f19fd, 0xfb3116fe, 0xfb3314fe, 0xfa3611ff, 0xfb370fff,
0xfb390dff, 0xfb3b0a00, 0xfc3d08ff, 0xfc3e0600, 0xfd3f0400,
0xfe3f0300, 0xff400100,
/* Vertical Filtering Coefficient(0x280-0x2fc) */
0x00004000, 0x000140ff, 0x00033ffe, 0x00043ffd, 0x00063efc,
0xff083dfc, 0x000a3bfb, 0xff0d39fb, 0xff0f37fb, 0xff1136fa,
0xfe1433fb, 0xfe1631fb, 0xfd192ffb, 0xfd1c2cfb, 0xfd1f29fb,
0xfc2127fc, 0xfc2424fc, 0xfc2721fc, 0xfb291ffd, 0xfb2c1cfd,
0xfb2f19fd, 0xfb3116fe, 0xfb3314fe, 0xfa3611ff, 0xfb370fff,
0xfb390dff, 0xfb3b0a00, 0xfc3d08ff, 0xfc3e0600, 0xfd3f0400,
0xfe3f0300, 0xff400100,
};
/* Set the Color Space Converter Coefficient Parameter */
void csc_coeff_set(void)
{
__u32 i, j;
/* 0x180-0x1ac */
for (i = 0, j = 0; i < 12; i++, j += 4)
write_wvalue(G2D_CSC01_ADDR_REG + j,
(((csc1coeff[i] & 0xFFFF) << 16) |
(csc0coeff[i] & 0xFFFF)));
/* 0x1c0-0x1ec */
for (i = 0, j = 0; i < 12; i++, j += 4)
write_wvalue(G2D_CSC2_ADDR_REG + j, csc2coeff[i]&0xFFFF);
}
/* Set the Scaling Horizontal/Vertical Filtering Coefficient Parameter */
void scaler_coeff_set(void)
{
__u32 i, j;
/* 0x200-0x2fc */
for (i = 0, j = 0; i < 64; i++, j += 4)
write_wvalue(G2D_SCALER_HFILTER_REG + j, scalercoeff[i]);
}
__u32 mixer_set_reg_base(unsigned long addr)
{
base_addr = addr;
return 0;
}
/* clear most of the registers value to default */
__u32 mixer_reg_init(void)
{
__u32 i;
for (i = 0; i <= 0x148; i += 4)
write_wvalue(i, 0);
write_wvalue(G2D_SCAN_ORDER_REG, 0x15FF0000);
/* initial the color space converter parameter */
csc_coeff_set();
/* initial the scaler coefficient parameter */
scaler_coeff_set();
return 0;
}
__u32 mixer_set_fillcolor(__u32 color, __u32 sel)
{
__u32 value;
if (sel == 1) {
value = read_wvalue(G2D_DMA1_CONTROL_REG) | G2D_FILL_ENABLE;
write_wvalue(G2D_DMA1_CONTROL_REG, value);
write_wvalue(G2D_DMA1_FILLCOLOR_REG, color);
} else if (sel == 2) {
value = read_wvalue(G2D_DMA2_CONTROL_REG) | G2D_FILL_ENABLE;
write_wvalue(G2D_DMA2_CONTROL_REG, value);
write_wvalue(G2D_DMA2_FILLCOLOR_REG, color);
} else if (sel == 3) {
value = read_wvalue(G2D_DMA3_CONTROL_REG) | G2D_FILL_ENABLE;
write_wvalue(G2D_DMA3_CONTROL_REG, value);
write_wvalue(G2D_DMA3_FILLCOLOR_REG, color);
} else {
value = read_wvalue(G2D_DMA0_CONTROL_REG) | G2D_FILL_ENABLE;
write_wvalue(G2D_DMA0_CONTROL_REG, value);
write_wvalue(G2D_DMA0_FILLCOLOR_REG, color);
}
return 0;
}
__u32 mixer_bpp_count(__u32 format)
{
__u32 bpp = 32;
switch (format) {
case G2D_FMT_1BPP_MONO:
case G2D_FMT_1BPP_PALETTE:
bpp = 1;
break;
case G2D_FMT_2BPP_MONO:
case G2D_FMT_2BPP_PALETTE:
bpp = 2;
break;
case G2D_FMT_4BPP_MONO:
case G2D_FMT_4BPP_PALETTE:
bpp = 4;
break;
case G2D_FMT_8BPP_MONO:
case G2D_FMT_8BPP_PALETTE:
case G2D_FMT_PYUV422UVC:
case G2D_FMT_PYUV420UVC:
case G2D_FMT_PYUV411UVC:
case G2D_FMT_PYUV422:
case G2D_FMT_PYUV420:
case G2D_FMT_PYUV411:
case G2D_FMT_PYUV422UVC_MB16:
case G2D_FMT_PYUV420UVC_MB16:
case G2D_FMT_PYUV411UVC_MB16:
case G2D_FMT_PYUV422UVC_MB32:
case G2D_FMT_PYUV420UVC_MB32:
case G2D_FMT_PYUV411UVC_MB32:
case G2D_FMT_PYUV422UVC_MB64:
case G2D_FMT_PYUV420UVC_MB64:
case G2D_FMT_PYUV411UVC_MB64:
case G2D_FMT_PYUV422UVC_MB128:
case G2D_FMT_PYUV420UVC_MB128:
case G2D_FMT_PYUV411UVC_MB128:
bpp = 8;
break;
case G2D_FMT_IYUV422:
case G2D_FMT_RGB565:
case G2D_FMT_BGR565:
case G2D_FMT_ARGB1555:
case G2D_FMT_ABGR1555:
case G2D_FMT_RGBA5551:
case G2D_FMT_BGRA5551:
case G2D_FMT_ARGB4444:
case G2D_FMT_ABGR4444:
case G2D_FMT_RGBA4444:
case G2D_FMT_BGRA4444:
bpp = 16;
break;
case G2D_FMT_ARGB_AYUV8888:
case G2D_FMT_BGRA_VUYA8888:
case G2D_FMT_ABGR_AVUY8888:
case G2D_FMT_RGBA_YUVA8888:
case G2D_FMT_XRGB8888:
case G2D_FMT_BGRX8888:
case G2D_FMT_XBGR8888:
case G2D_FMT_RGBX8888:
bpp = 32;
break;
default:
bpp = 32;
break;
}
return bpp;
}
__u32 mixer_in_fmtseq_set(__u32 format, __u32 pixel_seq)
{
__u32 val = 32;
switch (format) {
case G2D_FMT_1BPP_MONO:
case G2D_FMT_1BPP_PALETTE:
if (pixel_seq == G2D_SEQ_1BPP_LITTER_LITTER)
val = 0x3A;
else if (pixel_seq == G2D_SEQ_1BPP_BIG_LITTER)
val = 0x1A;
else if (pixel_seq == G2D_SEQ_1BPP_LITTER_BIG)
val = 0x2A;
else
val = 0xA;
break;
case G2D_FMT_2BPP_MONO:
case G2D_FMT_2BPP_PALETTE:
if (pixel_seq == G2D_SEQ_2BPP_LITTER_LITTER)
val = 0x39;
else if (pixel_seq == G2D_SEQ_2BPP_BIG_LITTER)
val = 0x19;
else if (pixel_seq == G2D_SEQ_2BPP_LITTER_BIG)
val = 0x29;
else
val = 0x9;
break;
case G2D_FMT_4BPP_MONO:
case G2D_FMT_4BPP_PALETTE:
if (pixel_seq == G2D_SEQ_P01234567)
val = 0x38;
else if (pixel_seq == G2D_SEQ_P67452301)
val = 0x18;
else if (pixel_seq == G2D_SEQ_P10325476)
val = 0x28;
else
val = 0x8;
break;
case G2D_FMT_8BPP_MONO:
case G2D_FMT_8BPP_PALETTE:
if (pixel_seq == G2D_SEQ_P0123)
val = 0x17;
else
val = 0x7;
break;
case G2D_FMT_PYUV422UVC:
case G2D_FMT_PYUV420UVC:
case G2D_FMT_PYUV411UVC:
case G2D_FMT_PYUV422UVC_MB16:
case G2D_FMT_PYUV420UVC_MB16:
case G2D_FMT_PYUV411UVC_MB16:
case G2D_FMT_PYUV422UVC_MB32:
case G2D_FMT_PYUV420UVC_MB32:
case G2D_FMT_PYUV411UVC_MB32:
case G2D_FMT_PYUV422UVC_MB64:
case G2D_FMT_PYUV420UVC_MB64:
case G2D_FMT_PYUV411UVC_MB64:
case G2D_FMT_PYUV422UVC_MB128:
case G2D_FMT_PYUV420UVC_MB128:
case G2D_FMT_PYUV411UVC_MB128:
val = 0x6;
break;
case G2D_FMT_IYUV422:
if (pixel_seq == G2D_SEQ_YVYU)
val = 0x14;
else
val = 0x4;
break;
case G2D_FMT_RGB565:
if (pixel_seq == G2D_SEQ_P01)
val = 0x13;
else
val = 0x3;
break;
case G2D_FMT_BGR565:
if (pixel_seq == G2D_SEQ_P01)
val = 0x93;
else
val = 0x83;
break;
case G2D_FMT_ARGB1555:
if (pixel_seq == G2D_SEQ_P01)
val = 0x12;
else
val = 0x2;
break;
case G2D_FMT_ABGR1555:
if (pixel_seq == G2D_SEQ_P01)
val = 0x92;
else
val = 0x82;
break;
case G2D_FMT_RGBA5551:
if (pixel_seq == G2D_SEQ_P01)
val = 0xb2;
else
val = 0xa2;
break;
case G2D_FMT_BGRA5551:
if (pixel_seq == G2D_SEQ_P01)
val = 0x32;
else
val = 0x22;
break;
case G2D_FMT_ARGB4444:
if (pixel_seq == G2D_SEQ_P01)
val = 0x11;
else
val = 0x01;
break;
case G2D_FMT_ABGR4444:
if (pixel_seq == G2D_SEQ_P01)
val = 0x91;
else
val = 0x81;
break;
case G2D_FMT_RGBA4444:
if (pixel_seq == G2D_SEQ_P01)
val = 0xb1;
else
val = 0xa1;
break;
case G2D_FMT_BGRA4444:
if (pixel_seq == G2D_SEQ_P01)
val = 0x31;
else
val = 0x21;
break;
case G2D_FMT_ARGB_AYUV8888:
case G2D_FMT_XRGB8888:
val = 0x0;
break;
case G2D_FMT_BGRA_VUYA8888:
case G2D_FMT_BGRX8888:
val = 0x20;
break;
case G2D_FMT_ABGR_AVUY8888:
case G2D_FMT_XBGR8888:
val = 0x80;
break;
case G2D_FMT_RGBA_YUVA8888:
case G2D_FMT_RGBX8888:
val = 0xa0;
break;
default:
val = 0;
break;
}
return val << 8;
}
__u32 mixer_in_csc_set(__u32 format)
{
__u32 val = 0;
switch (format) {
case G2D_FMT_IYUV422:
val = 0x11;
break;
case G2D_FMT_PYUV422UVC:
case G2D_FMT_PYUV422UVC_MB16:
case G2D_FMT_PYUV422UVC_MB32:
case G2D_FMT_PYUV422UVC_MB64:
case G2D_FMT_PYUV422UVC_MB128:
val = 0x21;
break;
case G2D_FMT_PYUV420UVC:
case G2D_FMT_PYUV420UVC_MB16:
case G2D_FMT_PYUV420UVC_MB32:
case G2D_FMT_PYUV420UVC_MB64:
case G2D_FMT_PYUV420UVC_MB128:
val = 0x31;
break;
case G2D_FMT_PYUV411UVC:
case G2D_FMT_PYUV411UVC_MB16:
case G2D_FMT_PYUV411UVC_MB32:
case G2D_FMT_PYUV411UVC_MB64:
case G2D_FMT_PYUV411UVC_MB128:
val = 0x41;
break;
default:
val = 0;
break;
}
return val;
}
__u32 mixer_out_fmtseq_set(__u32 format, __u32 pixel_seq)
{
__u32 val = 0;
switch (format) {
case G2D_FMT_1BPP_MONO:
if (pixel_seq == G2D_SEQ_1BPP_LITTER_LITTER)
val = 0x38A;
else if (pixel_seq == G2D_SEQ_1BPP_BIG_LITTER)
val = 0x18A;
else if (pixel_seq == G2D_SEQ_1BPP_LITTER_BIG)
val = 0x28A;
else
val = 0x8A;
break;
case G2D_FMT_2BPP_MONO:
if (pixel_seq == G2D_SEQ_2BPP_LITTER_LITTER)
val = 0x389;
else if (pixel_seq == G2D_SEQ_2BPP_BIG_LITTER)
val = 0x189;
else if (pixel_seq == G2D_SEQ_2BPP_LITTER_BIG)
val = 0x289;
else
val = 0x89;
break;
case G2D_FMT_4BPP_MONO:
if (pixel_seq == G2D_SEQ_P01234567)
val = 0x388;
else if (pixel_seq == G2D_SEQ_P67452301)
val = 0x188;
else if (pixel_seq == G2D_SEQ_P10325476)
val = 0x288;
else
val = 0x88;
break;
case G2D_FMT_8BPP_MONO:
if (pixel_seq == G2D_SEQ_P0123)
val = 0x187;
else
val = 0x87;
break;
case G2D_FMT_PYUV422:
val = 0x86;
break;
case G2D_FMT_PYUV422UVC:
val = 0x85;
break;
case G2D_FMT_PYUV420UVC:
val = 0x8b;
break;
case G2D_FMT_PYUV420:
val = 0x8c;
break;
case G2D_FMT_PYUV411UVC:
val = 0x8d;
break;
case G2D_FMT_PYUV411:
val = 0x8e;
break;
case G2D_FMT_IYUV422:
if (pixel_seq == G2D_SEQ_YVYU)
val = 0x184;
else
val = 0x84;
break;
case G2D_FMT_RGB565:
if (pixel_seq == G2D_SEQ_P01)
val = 0x183;
else
val = 0x3;
break;
case G2D_FMT_BGR565:
if (pixel_seq == G2D_SEQ_P01)
val = 0x983;
else
val = 0x883;
break;
case G2D_FMT_ARGB1555:
if (pixel_seq == G2D_SEQ_P01)
val = 0x182;
else
val = 0x82;
break;
case G2D_FMT_ABGR1555:
if (pixel_seq == G2D_SEQ_P01)
val = 0x982;
else
val = 0x882;
break;
case G2D_FMT_RGBA5551:
if (pixel_seq == G2D_SEQ_P01)
val = 0xb82;
else
val = 0xa82;
break;
case G2D_FMT_BGRA5551:
if (pixel_seq == G2D_SEQ_P01)
val = 0x382;
else
val = 0x282;
break;
case G2D_FMT_ARGB4444:
if (pixel_seq == G2D_SEQ_P01)
val = 0x181;
else
val = 0x81;
break;
case G2D_FMT_ABGR4444:
if (pixel_seq == G2D_SEQ_P01)
val = 0x981;
else
val = 0x881;
break;
case G2D_FMT_RGBA4444:
if (pixel_seq == G2D_SEQ_P01)
val = 0xb81;
else
val = 0xa81;
break;
case G2D_FMT_BGRA4444:
if (pixel_seq == G2D_SEQ_P01)
val = 0x381;
else
val = 0x281;
break;
case G2D_FMT_ARGB_AYUV8888:
case G2D_FMT_XRGB8888:
val = 0x80;
break;
case G2D_FMT_BGRA_VUYA8888:
case G2D_FMT_BGRX8888:
val = 0x280;
break;
case G2D_FMT_ABGR_AVUY8888:
case G2D_FMT_XBGR8888:
val = 0x880;
break;
case G2D_FMT_RGBA_YUVA8888:
case G2D_FMT_RGBX8888:
val = 0xa80;
break;
default:
val = 80;
break;
}
return val;
}
__u64 mixer_get_addr(__u32 buffer_addr, __u32 format, __u32 stride,
__u32 x, __u32 y)
{
__u32 bpp = 0;
__u64 addr = 0;
bpp = mixer_bpp_count(format);
addr = (__u64) (buffer_addr) * 8 +
(__u64) ((stride * y + x) * bpp); /* bits */
return addr;
}
__u32 mixer_get_irq(void)
{
__u32 reg_val = 0;
reg_val = read_wvalue(G2D_STATUS_REG);
return reg_val;
}
__u32 mixer_get_irq0(void)
{
__u32 reg_val = 0;
reg_val = read_wvalue(G2D_CMDQ_STS_REG);
return reg_val;
}
__u32 mixer_clear_init(void)
{
write_wvalue(G2D_STATUS_REG, 0x300);
write_wvalue(G2D_CONTROL_REG, 0x0);
return 0;
}
__u32 mixer_clear_init0(void)
{
write_wvalue(G2D_CMDQ_STS_REG, 0x100);
write_wvalue(G2D_CMDQ_CTL_REG, 0x0);
return 0;
}
__u32 mixer_set_rotate_reg(__u32 flag)
{
__u32 rot = 0;
if (flag & G2D_BLT_FLIP_HORIZONTAL)
rot = 0x10;
else if (flag & G2D_BLT_FLIP_VERTICAL)
rot = 0x20;
else if (flag & G2D_BLT_ROTATE90)
rot = 0x50;
else if (flag & G2D_BLT_ROTATE180)
rot = 0x30;
else if (flag & G2D_BLT_ROTATE270)
rot = 0x60;
else if (flag & G2D_BLT_MIRROR45)
rot = 0x70;
else if (flag & G2D_BLT_MIRROR135)
rot = 0x40;
else
rot = 0;
return rot;
}
__s32 mixer_fillrectangle(g2d_fillrect *para)
{
__u32 reg_val = 0;
__u64 addr_val;
__s32 result = 0;
mixer_reg_init();/* initial mixer register */
/* channel0 is the fill surface */
write_wvalue(G2D_DMA0_SIZE_REG,
(para->dst_rect.w - 1) | ((para->dst_rect.h - 1) << 16));
/* globe alpha mode */
if (para->flag & G2D_FIL_PLANE_ALPHA)
reg_val |= (para->alpha << 24) | 0x4;
else if (para->flag & G2D_FIL_MULTI_ALPHA)
reg_val |= (para->alpha << 24) | 0x8;
reg_val |= 0x1;
write_wvalue(G2D_DMA0_CONTROL_REG, reg_val);
mixer_set_fillcolor(para->color, 0);
if ((para->flag & G2D_FIL_PLANE_ALPHA)
|| (para->flag & G2D_FIL_PIXEL_ALPHA)
|| (para->flag & G2D_FIL_MULTI_ALPHA)) {
/* channel3 is the dst surface */
addr_val =
mixer_get_addr(para->dst_image.addr[0],
para->dst_image.format, para->dst_image.w,
para->dst_rect.x, para->dst_rect.y);
reg_val = (addr_val >> 32) & 0xF; /* high addr in bits */
write_wvalue(G2D_DMA_HADDR_REG, reg_val << 24);
reg_val = addr_val & 0xFFFFFFFF; /* low addr in bits */
write_wvalue(G2D_DMA3_LADDR_REG, reg_val);
write_wvalue(G2D_DMA3_STRIDE_REG,
para->dst_image.w *
mixer_bpp_count(para->dst_image.format));
write_wvalue(G2D_DMA3_SIZE_REG,
(para->dst_rect.w -
1) | ((para->dst_rect.h - 1) << 16));
reg_val = read_wvalue(G2D_DMA3_CONTROL_REG);
/* palette format */
if (para->dst_image.format > 0x19)
reg_val |= 0x2;
reg_val |=
G2D_IDMA_ENABLE | mixer_in_fmtseq_set(para->dst_image.
format,
para->dst_image.
pixel_seq);
write_wvalue(G2D_DMA3_CONTROL_REG, reg_val);
write_wvalue(G2D_CK_CONTROL_REG, 0x1);
}
write_wvalue(G2D_ROP_INDEX0_REG, 0x840);
/* output surface is the dst surface */
write_wvalue(G2D_OUTPUT_SIZE_REG,
(para->dst_rect.w - 1) | ((para->dst_rect.h - 1) << 16));
addr_val =
mixer_get_addr(para->dst_image.addr[0], para->dst_image.format,
para->dst_image.w, para->dst_rect.x,
para->dst_rect.y);
reg_val = (addr_val >> 32) & 0xF; /* high addr in bits */
write_wvalue(G2D_OUTPUT_HADDR_REG, reg_val);
reg_val = addr_val & 0xFFFFFFFF; /* low addr in bits */
write_wvalue(G2D_OUTPUT0_LADDR_REG, reg_val);
write_wvalue(G2D_OUTPUT0_STRIDE_REG,
para->dst_image.w *
mixer_bpp_count(para->dst_image.format));
write_wvalue(G2D_OUTPUT_CONTROL_REG,
mixer_out_fmtseq_set(para->dst_image.format,
para->dst_image.pixel_seq));
/* start */
write_wvalue(G2D_CONTROL_REG, 0);
write_wvalue(G2D_CONTROL_REG, 0x303);
result = g2d_wait_cmd_finish();
return result;
}
__s32 mixer_blt(g2d_blt *para, enum g2d_scan_order scan_order)
{
__u32 bppnum = 0;
__u32 reg_val = 0;
__u64 addr_val;
__s32 result = 0;
__u32 i, j;
mixer_reg_init(); /* initial mixer register */
if ((para->dst_image.format > 0x16) && (para->dst_image.format < 0x1A)
&& (para->dst_image.pixel_seq == G2D_SEQ_VUVU)) {
for (i = 0, j = 0; i < 12; i++, j += 4)
write_wvalue(G2D_CSC2_ADDR_REG + j,
csc2coeff_VUVU[i] & 0xFFFF);
/* 0x1c0-0x1ec */
}
/* src surface */
addr_val =
mixer_get_addr(para->src_image.addr[0], para->src_image.format,
para->src_image.w, para->src_rect.x,
para->src_rect.y);
reg_val = (addr_val >> 32) & 0xF; /* high addr in bits */
write_wvalue(G2D_DMA_HADDR_REG, reg_val);
reg_val = addr_val & 0xFFFFFFFF; /* low addr in bits */
write_wvalue(G2D_DMA0_LADDR_REG, reg_val);
write_wvalue(G2D_DMA0_STRIDE_REG,
para->src_image.w *
mixer_bpp_count(para->src_image.format));
write_wvalue(G2D_DMA0_SIZE_REG,
(para->src_rect.w - 1) | ((para->src_rect.h - 1) << 16));
reg_val = read_wvalue(G2D_DMA0_CONTROL_REG);
reg_val |=
mixer_in_fmtseq_set(para->src_image.format,
para->src_image.pixel_seq) | G2D_IDMA_ENABLE;
/* rgbx/bgrx/xrgb/xbgr format */
if ((para->src_image.format > 0x03) && (para->src_image.format < 0x08))
reg_val |= (0xFF << 24) | 0x4;
/* palette format */
if ((para->src_image.format > 0x1C) && (para->src_image.format < 0x21))
reg_val |= 0x2;
/* globe alpha mode */
if (para->flag & G2D_BLT_PLANE_ALPHA)
reg_val |= (para->alpha << 24) | 0x4;
else if (para->flag & G2D_BLT_MULTI_ALPHA)
reg_val |= (para->alpha << 24) | 0x8;
/* rotate/mirror */
reg_val |= mixer_set_rotate_reg(para->flag);
write_wvalue(G2D_DMA0_CONTROL_REG, reg_val);
reg_val = mixer_in_csc_set(para->src_image.format);
write_wvalue(G2D_CSC0_CONTROL_REG, reg_val);
reg_val = mixer_in_csc_set(para->dst_image.format);
write_wvalue(G2D_CSC1_CONTROL_REG, reg_val);
/* pyuv422/420/411uvc */
if ((para->src_image.format > 0x16) &&
(para->src_image.format < 0x1A)) {
if (para->src_image.format == G2D_FMT_PYUV411UVC)
bppnum = 4;
else
bppnum = 8;
if (para->src_image.format == G2D_FMT_PYUV420UVC)
addr_val =
(__u64) para->src_image.addr[1] * 8 +
(__u64) ((para->src_image.w *
(para->src_rect.y / 2) +
para->src_rect.x) * bppnum);
else
addr_val =
(__u64) para->src_image.addr[1] * 8 +
(__u64) ((para->src_image.w * para->src_rect.y +
para->src_rect.x) * bppnum);
reg_val = read_wvalue(G2D_DMA_HADDR_REG);
reg_val |= ((addr_val >> 32) & 0xF) << 8;/* high addr in bits */
write_wvalue(G2D_DMA_HADDR_REG, reg_val);
reg_val = addr_val & 0xFFFFFFFF; /* low addr in bits */
write_wvalue(G2D_DMA1_LADDR_REG, reg_val);
write_wvalue(G2D_DMA1_STRIDE_REG, para->src_image.w * bppnum);
write_wvalue(G2D_DMA1_SIZE_REG,
(para->src_rect.w -
1) | ((para->src_rect.h - 1) << 16));
reg_val = read_wvalue(G2D_DMA1_CONTROL_REG);
reg_val |= (5 << 8) | G2D_IDMA_ENABLE;
/* rotate/mirror */
reg_val |= mixer_set_rotate_reg(para->flag);
write_wvalue(G2D_DMA1_CONTROL_REG, reg_val);
}
mixer_micro_block_set(para);
write_wvalue(G2D_DMA1_FILLCOLOR_REG, 0xFFFFFFFF);
write_wvalue(G2D_DMA2_FILLCOLOR_REG, 0xFFFFFFFF);
if ((para->flag & G2D_BLT_PIXEL_ALPHA)
|| (para->flag & G2D_BLT_PLANE_ALPHA)
|| (para->flag & G2D_BLT_MULTI_ALPHA)
|| (para->flag & G2D_BLT_SRC_COLORKEY)
|| (para->flag & G2D_BLT_DST_COLORKEY)) {
/* pyuv422/420/411uvc */
if ((para->dst_image.format > 0x16)
&& (para->dst_image.format < 0x1A)) {
if (para->dst_image.format == G2D_FMT_PYUV411UVC)
bppnum = 4;
else
bppnum = 8;
if (para->dst_image.format == G2D_FMT_PYUV420UVC)
addr_val =
(__u64) para->dst_image.addr[1] * 8 +
(__u64) ((para->dst_image.w *
(para->dst_y / 2) +
para->dst_x) * bppnum);
else
addr_val =
(__u64) para->dst_image.addr[1] * 8 +
(__u64) ((para->dst_image.w * para->dst_y +
para->dst_x) * bppnum);
reg_val = read_wvalue(G2D_DMA_HADDR_REG);
/* high addr in bits */
reg_val |= ((addr_val >> 32) & 0xF) << 16;
write_wvalue(G2D_DMA_HADDR_REG, reg_val);
/* low addr in bits */
reg_val = addr_val & 0xFFFFFFFF;
write_wvalue(G2D_DMA2_LADDR_REG, reg_val);
write_wvalue(G2D_DMA2_STRIDE_REG,
para->dst_image.w * bppnum);
write_wvalue(G2D_DMA2_SIZE_REG,
(para->src_rect.w -
1) | ((para->src_rect.h - 1) << 16));
reg_val = read_wvalue(G2D_DMA2_CONTROL_REG);
reg_val |= (5 << 8) | G2D_IDMA_ENABLE;
write_wvalue(G2D_DMA2_CONTROL_REG, reg_val);
}
/* channel3 is dst surface */
addr_val =
mixer_get_addr(para->dst_image.addr[0],
para->dst_image.format, para->dst_image.w,
para->dst_x, para->dst_y);
reg_val = read_wvalue(G2D_DMA_HADDR_REG);
reg_val |= ((addr_val >> 32) & 0xF) << 24;/*high addr in bits*/
write_wvalue(G2D_DMA_HADDR_REG, reg_val);
reg_val = addr_val & 0xFFFFFFFF; /* low addr in bits */
write_wvalue(G2D_DMA3_LADDR_REG, reg_val);
write_wvalue(G2D_DMA3_STRIDE_REG,
para->dst_image.w *
mixer_bpp_count(para->dst_image.format));
if ((para->flag & G2D_BLT_ROTATE90)
|| (para->flag & G2D_BLT_ROTATE270))
write_wvalue(G2D_DMA3_SIZE_REG,
(para->src_rect.h -
1) | ((para->src_rect.w - 1) << 16));
else
write_wvalue(G2D_DMA3_SIZE_REG,
(para->src_rect.w -
1) | ((para->src_rect.h - 1) << 16));
reg_val = read_wvalue(G2D_DMA3_CONTROL_REG);
reg_val |=
mixer_in_fmtseq_set(para->dst_image.format,
para->dst_image.
pixel_seq) | G2D_IDMA_ENABLE;
/* rgbx/bgrx/xrgb/xbgr format */
if ((para->dst_image.format > 0x03)
&& (para->dst_image.format < 0x08)) {
reg_val |= (0xFF << 24) | 0x4;
}
write_wvalue(G2D_DMA3_CONTROL_REG, reg_val);
}
/* colorkey */
if (para->flag & G2D_BLT_SRC_COLORKEY) {
reg_val = 0x3;
} else if (para->flag & G2D_BLT_DST_COLORKEY) {
reg_val = 0x5;
} else if ((para->flag & G2D_BLT_PIXEL_ALPHA)
|| (para->flag & G2D_BLT_PLANE_ALPHA)
|| (para->flag & G2D_BLT_MULTI_ALPHA)) {
reg_val = 0x1;
} else {
reg_val = 0x0;
}
write_wvalue(G2D_CK_CONTROL_REG, reg_val);
write_wvalue(G2D_CK_MINCOLOR_REG, para->color);
write_wvalue(G2D_CK_MAXCOLOR_REG, para->color);
/* output surface is the dst surface */
if ((para->flag & G2D_BLT_ROTATE90) ||
(para->flag & G2D_BLT_ROTATE270)) {
write_wvalue(G2D_OUTPUT_SIZE_REG,
(para->src_rect.h -
1) | ((para->src_rect.w - 1) << 16));
} else {
write_wvalue(G2D_OUTPUT_SIZE_REG,
(para->src_rect.w -
1) | ((para->src_rect.h - 1) << 16));
}
addr_val =
mixer_get_addr(para->dst_image.addr[0], para->dst_image.format,
para->dst_image.w, para->dst_x, para->dst_y);
reg_val = (addr_val >> 32) & 0xF; /* high addr in bits */
write_wvalue(G2D_OUTPUT_HADDR_REG, reg_val);
reg_val = addr_val & 0xFFFFFFFF; /* low addr in bits */
write_wvalue(G2D_OUTPUT0_LADDR_REG, reg_val);
write_wvalue(G2D_OUTPUT0_STRIDE_REG,
para->dst_image.w *
mixer_bpp_count(para->dst_image.format));
reg_val =
mixer_out_fmtseq_set(para->dst_image.format,
para->dst_image.pixel_seq);
write_wvalue(G2D_OUTPUT_CONTROL_REG, reg_val);
if ((para->dst_image.format > 0x16) &&
(para->dst_image.format < 0x1D)) {
if ((para->dst_image.format == G2D_FMT_PYUV411UVC)
|| (para->dst_image.format == G2D_FMT_PYUV422)
|| (para->dst_image.format == G2D_FMT_PYUV420))
bppnum = 4;
else if (para->dst_image.format == G2D_FMT_PYUV411)
bppnum = 2;
else
bppnum = 8;
if ((para->dst_image.format == G2D_FMT_PYUV420UVC)
|| (para->dst_image.format == G2D_FMT_PYUV420))
addr_val =
(__u64) para->dst_image.addr[1] * 8 +
(__u64) ((para->dst_image.w * (para->dst_y / 2) +
para->dst_x) * bppnum);
else
addr_val =
(__u64) para->dst_image.addr[1] * 8 +
(__u64) ((para->dst_image.w * para->dst_y +
para->dst_x) * bppnum);
reg_val = read_wvalue(G2D_OUTPUT_HADDR_REG);
reg_val |= ((addr_val >> 32) & 0xF) << 8;/* high addr in bits */
write_wvalue(G2D_OUTPUT_HADDR_REG, reg_val);
reg_val = addr_val & 0xFFFFFFFF; /* low addr in bits */
write_wvalue(G2D_OUTPUT1_LADDR_REG, reg_val);
write_wvalue(G2D_OUTPUT1_STRIDE_REG,
para->dst_image.w * bppnum);
if (para->dst_image.format == G2D_FMT_PYUV420)
addr_val =
(__u64) para->dst_image.addr[2] * 8 +
(__u64) ((para->dst_image.w * (para->dst_y / 2) +
para->dst_x) * bppnum);
else if ((para->dst_image.format == G2D_FMT_PYUV422)
|| (para->dst_image.format == G2D_FMT_PYUV411))
addr_val =
(__u64) para->dst_image.addr[2] * 8 +
(__u64) ((para->dst_image.w * para->dst_y +
para->dst_x) * bppnum);
else
addr_val = 0;
reg_val = read_wvalue(G2D_OUTPUT_HADDR_REG);
reg_val |= ((addr_val >> 32) & 0xF) << 16;/*high addr in bits*/
write_wvalue(G2D_OUTPUT_HADDR_REG, reg_val);
reg_val = addr_val & 0xFFFFFFFF; /* low addr in bits */
write_wvalue(G2D_OUTPUT2_LADDR_REG, reg_val);
write_wvalue(G2D_OUTPUT2_STRIDE_REG,
para->dst_image.w * bppnum);
write_wvalue(G2D_CSC2_CONTROL_REG, 0x1);
}
if ((para->dst_image.format > 0x11) && (para->dst_image.format < 0x1D))
write_wvalue(G2D_CSC2_CONTROL_REG, 0x1);
if ((para->flag & G2D_BLT_PIXEL_ALPHA) | (para->
flag & G2D_BLT_PLANE_ALPHA) |
(para->flag & G2D_BLT_MULTI_ALPHA) | (para->
flag & G2D_BLT_SRC_COLORKEY) |
(para->flag & G2D_BLT_DST_COLORKEY))
write_wvalue(G2D_OALPHA_CONTROL_REG, 0x80);
/* 0x40: A2 area keep the dst alpha,0x80: A2 area keep the
* src+dst(1-src) alpha value
*/
mixer_premultiply_set(para->flag);
/*scan order */
write_wvalue(G2D_SCAN_ORDER_REG, (scan_order & 0x3) << 8);
/* start */
write_wvalue(G2D_CONTROL_REG, 0x0);
write_wvalue(G2D_CONTROL_REG, 0x303);
result = g2d_wait_cmd_finish();
return result;
}
__s32 mixer_stretchblt(g2d_stretchblt *para, enum g2d_scan_order scan_order)
{
__u32 bppnum = 0;
__u32 reg_val = 0;
__u32 reg_tmp = 0;
__u64 addr_val;
__u32 cnt, sinw, soutw, scaler_inx, scaler_iny, scaler_outx;
__u32 scaler_outy, i;
__s32 result = 0;
mixer_reg_init();/* initial mixer register */
/* src surface */
write_wvalue(G2D_DMA0_STRIDE_REG,
para->src_image.w *
mixer_bpp_count(para->src_image.format));
reg_val = read_wvalue(G2D_DMA0_CONTROL_REG);
reg_val |=
mixer_in_fmtseq_set(para->src_image.format,
para->src_image.pixel_seq) | G2D_IDMA_ENABLE;
/* rgbx/bgrx/xrgb/xbgr format */
if ((para->src_image.format > 0x03) &&
(para->src_image.format < 0x08)) {
reg_val |= (0xFF<<24)|0x4;
}
/* palette format */
if (para->src_image.format > 0x1C)
reg_val |= 0x2;
/* globe alpha mode */
if (para->flag & G2D_BLT_PLANE_ALPHA)
reg_val |= (para->alpha<<24)|0x4;
else if (para->flag & G2D_BLT_MULTI_ALPHA)
reg_val |= (para->alpha<<24)|0x8;
/* rotate/mirror */
reg_val |= mixer_set_rotate_reg(para->flag);
write_wvalue(G2D_DMA0_CONTROL_REG, reg_val);
reg_val = mixer_in_csc_set(para->src_image.format);
write_wvalue(G2D_CSC0_CONTROL_REG, reg_val);
reg_val = mixer_in_csc_set(para->dst_image.format);
write_wvalue(G2D_CSC1_CONTROL_REG, reg_val);
/* sacler setting */
write_wvalue(G2D_SCALER_CONTROL_REG,
G2D_SCALER_4TAP4 | G2D_SCALER_ENABLE);
write_wvalue(G2D_SCALER_HPHASE_REG, 0);
write_wvalue(G2D_SCALER_VPHASE_REG, 0);
write_wvalue(G2D_ROP_INDEX0_REG, 0x840);
/* channel3 is dst surface */
write_wvalue(G2D_DMA3_STRIDE_REG,
para->dst_image.w *
mixer_bpp_count(para->dst_image.format));
reg_val = read_wvalue(G2D_DMA3_CONTROL_REG);
reg_val |=
mixer_in_fmtseq_set(para->dst_image.format,
para->dst_image.pixel_seq);
if ((para->flag & G2D_BLT_PIXEL_ALPHA)
|| (para->flag & G2D_BLT_PLANE_ALPHA)
|| (para->flag & G2D_BLT_MULTI_ALPHA)
|| (para->flag & G2D_BLT_SRC_COLORKEY)
|| (para->flag & G2D_BLT_DST_COLORKEY))
reg_val |= G2D_IDMA_ENABLE;
/* rgbx/bgrx/xrgb/xbgr format */
if ((para->src_image.format > 0x03) && (para->src_image.format < 0x08))
reg_val |= (0xFF<<24)|0x4;
write_wvalue(G2D_DMA3_CONTROL_REG, reg_val);
/* colorkey */
if (para->flag & G2D_BLT_SRC_COLORKEY)
reg_val = 0x3;
else if (para->flag & G2D_BLT_DST_COLORKEY)
reg_val = 0x5;
else if ((para->flag & G2D_BLT_PIXEL_ALPHA)
|| (para->flag & G2D_BLT_PLANE_ALPHA)
|| (para->flag & G2D_BLT_MULTI_ALPHA))
reg_val = 1;
else
reg_val = 0x0;
write_wvalue(G2D_CK_CONTROL_REG, reg_val);
write_wvalue(G2D_CK_MINCOLOR_REG, para->color);
write_wvalue(G2D_CK_MAXCOLOR_REG, para->color);
write_wvalue(G2D_OUTPUT0_STRIDE_REG,
para->dst_image.w *
mixer_bpp_count(para->dst_image.format));
reg_val =
mixer_out_fmtseq_set(para->dst_image.format,
para->dst_image.pixel_seq);
write_wvalue(G2D_OUTPUT_CONTROL_REG, reg_val);
if ((para->flag & G2D_BLT_PIXEL_ALPHA) | (para->
flag & G2D_BLT_PLANE_ALPHA) |
(para->flag & G2D_BLT_MULTI_ALPHA) | (para->
flag & G2D_BLT_SRC_COLORKEY) |
(para->flag & G2D_BLT_DST_COLORKEY))
write_wvalue(G2D_OALPHA_CONTROL_REG, 0x80);
/* 0x40: A2 area keep the dst alpha,0x80: A2 area keep the
* src+dst(1-src) alpha value
*/
mixer_premultiply_set(para->flag);
/* output width lager than 1024 pixel width */
if (para->dst_rect.w > 0x400) {
/* scaler up divide the output into 1024 pixel width part */
cnt = para->dst_rect.w / 1024;
cnt = (para->dst_rect.w % 1024) ? cnt : cnt - 1;
sinw = (para->src_rect.w / para->dst_rect.w) << 10;
sinw |=
((para->src_rect.w % para->dst_rect.w) << 10) /
para->dst_rect.w;
if ((para->flag & G2D_BLT_ROTATE90)
|| (para->flag & G2D_BLT_ROTATE270)) {
sinw = (para->src_rect.h / para->dst_rect.w) << 10;
sinw |=
((para->src_rect.h % para->dst_rect.w) << 10) /
para->dst_rect.w;
}
scaler_inx = para->src_rect.x;
scaler_iny = para->src_rect.y;
scaler_outx = para->dst_rect.x;
scaler_outy = para->dst_rect.y;
for (i = 0; i < cnt; i++) {
/* DMA0 */
addr_val =
mixer_get_addr(para->src_image.addr[0],
para->src_image.format,
para->src_image.w, scaler_inx,
para->src_rect.y);
reg_val = (addr_val >> 32) & 0xF;/* high addr in bits */
write_wvalue(G2D_DMA_HADDR_REG, reg_val);
reg_val = addr_val&0xFFFFFFFF;/* low addr in bits */
write_wvalue(G2D_DMA0_LADDR_REG, reg_val);
if (sinw < 1)
sinw = 1;
write_wvalue(G2D_DMA0_SIZE_REG, (sinw - 1) |
((para->src_rect.h - 1)<<16));
if ((para->flag & G2D_BLT_ROTATE90) ||
(para->flag & G2D_BLT_ROTATE270))
write_wvalue(G2D_DMA0_SIZE_REG,
(para->src_rect.w - 1) |
((sinw - 1)<<16));
/* DMA1 pyuv422/420/411uvc */
if ((para->src_image.format > 0x16) &&
(para->src_image.format < 0x1A)) {
if (para->src_image.format ==
G2D_FMT_PYUV411UVC)
bppnum = 4;
else
bppnum = 8;
if (para->src_image.format ==
G2D_FMT_PYUV420UVC)
addr_val = (__u64)para->src_image.addr[1] * 8 +
(__u64)((para->src_image.w *
(para->src_rect.y/2) +
scaler_inx) * bppnum);
else
addr_val = (__u64)para->src_image.addr[1] * 8 +
(__u64)((para->src_image.w *
para->src_rect.y +
scaler_inx) * bppnum);
reg_val = read_wvalue(G2D_DMA_HADDR_REG);
/* high addr in bits */
reg_val |= ((addr_val>>32)&0xF)<<8;
write_wvalue(G2D_DMA_HADDR_REG, reg_val);
/* low addr in bits */
reg_val = addr_val&0xFFFFFFFF;
write_wvalue(G2D_DMA1_LADDR_REG, reg_val);
write_wvalue(G2D_DMA1_STRIDE_REG,
para->src_image.w * bppnum);
if (sinw < 1)
sinw = 1;
write_wvalue(G2D_DMA1_SIZE_REG, (sinw - 1) |
((para->src_rect.h - 1)<<16));
reg_val = read_wvalue(G2D_DMA1_CONTROL_REG);
reg_val |= (5 << 8) | G2D_IDMA_ENABLE;
/* rotate/mirror */
reg_val |= mixer_set_rotate_reg(para->flag);
write_wvalue(G2D_DMA1_CONTROL_REG, reg_val);
}
/* scaler setting */
if ((para->flag & G2D_BLT_ROTATE90) ||
(para->flag & G2D_BLT_ROTATE270)) {
write_wvalue(G2D_SCALER_SIZE_REG,
(para->dst_rect.h - 1) | ((0x400 - 1)<<16));
reg_val = (para->src_rect.w/para->dst_rect.h)<<16;
reg_tmp = (para->src_rect.w%para->dst_rect.h);
reg_val |= (reg_tmp<<16)/para->dst_rect.h;
write_wvalue(G2D_SCALER_HFACTOR_REG, reg_val);
reg_val = (sinw/0x400)<<16;
reg_tmp = (sinw%0x400);
reg_val |= (reg_tmp<<16)/0x400;
write_wvalue(G2D_SCALER_VFACTOR_REG, reg_val);
} else {
write_wvalue(G2D_SCALER_SIZE_REG,
(0x400 - 1) | ((para->dst_rect.h - 1)<<16));
reg_val = (sinw/0x400)<<16;
reg_tmp = (sinw%0x400);
reg_val |= (reg_tmp<<16)/0x400;
write_wvalue(G2D_SCALER_HFACTOR_REG, reg_val);
reg_val = (para->src_rect.h/para->dst_rect.h)<<16;
reg_tmp = (para->src_rect.h%para->dst_rect.h);
reg_val |= (reg_tmp<<16)/para->dst_rect.h;
write_wvalue(G2D_SCALER_VFACTOR_REG, reg_val);
}
if ((para->flag & G2D_BLT_PIXEL_ALPHA) ||
(para->flag & G2D_BLT_PLANE_ALPHA) ||
(para->flag & G2D_BLT_MULTI_ALPHA) ||
(para->flag & G2D_BLT_SRC_COLORKEY) ||
(para->flag & G2D_BLT_DST_COLORKEY)) {
/* DMA2 pyuv422/420/411uvc */
if ((para->dst_image.format > 0x16) &&
(para->dst_image.format < 0x1A)) {
if (para->dst_image.format ==
G2D_FMT_PYUV411UVC)
bppnum = 4;
else
bppnum = 8;
if (para->dst_image.format ==
G2D_FMT_PYUV420UVC)
addr_val = (__u64)para->dst_image.addr[1] * 8 +
(__u64)((para->dst_image.w *
(para->dst_rect.y / 2) +
scaler_outx) * bppnum);
else
addr_val = (__u64)para->dst_image.addr[1] * 8 +
(__u64)((para->dst_image.w *
para->dst_rect.y +
scaler_outx) * bppnum);
reg_val = read_wvalue(G2D_DMA_HADDR_REG);
/* high addr in bits */
reg_val |= ((addr_val>>32)&0xF)<<16;
write_wvalue(G2D_DMA_HADDR_REG, reg_val);
/* low addr in bits */
reg_val = addr_val&0xFFFFFFFF;
write_wvalue(G2D_DMA2_LADDR_REG, reg_val);
write_wvalue(G2D_DMA2_STRIDE_REG,
para->dst_image.w*bppnum);
write_wvalue(G2D_DMA2_SIZE_REG, (0x400 - 1) |
((para->dst_rect.h - 1)<<16));
reg_val = read_wvalue(G2D_DMA2_CONTROL_REG);
reg_val |= (5<<8) | G2D_IDMA_ENABLE;
write_wvalue(G2D_DMA2_CONTROL_REG, reg_val);
}
/* DMA3 */
addr_val = mixer_get_addr(para->dst_image.addr[0],
para->dst_image.format,
para->dst_image.w, scaler_outx,
para->dst_rect.y);
reg_val = read_wvalue(G2D_DMA_HADDR_REG);
reg_val = reg_val & 0xF0FFFFFF;
/* high addr in bits */
reg_val |= ((addr_val>>32)&0xF)<<24;
write_wvalue(G2D_DMA_HADDR_REG, reg_val);
reg_val = addr_val&0xFFFFFFFF;/* low addr in bits */
write_wvalue(G2D_DMA3_LADDR_REG, reg_val);
write_wvalue(G2D_DMA3_SIZE_REG, (0x400 - 1) |
((para->dst_rect.h - 1)<<16));
}
/* OUT */
write_wvalue(G2D_OUTPUT_SIZE_REG, (0x400 - 1) |
((para->dst_rect.h - 1)<<16));
if ((para->flag & G2D_BLT_ROTATE180))
scaler_outx = para->dst_rect.w - 0x400;
addr_val = mixer_get_addr(para->dst_image.addr[0],
para->dst_image.format,
para->dst_image.w, scaler_outx,
scaler_outy);
if ((para->flag & G2D_BLT_ROTATE270))
addr_val = mixer_get_addr(para->dst_image.addr[0],
para->dst_image.format,
para->dst_image.w,
scaler_outx-0x400,
scaler_outy);
reg_val = (addr_val>>32)&0xF;/* high addr in bits */
write_wvalue(G2D_OUTPUT_HADDR_REG, reg_val);
reg_val = addr_val&0xFFFFFFFF;/* low addr in bits */
write_wvalue(G2D_OUTPUT0_LADDR_REG, reg_val);
/* OUT1 */
if ((para->dst_image.format > 0x16) &&
(para->dst_image.format < 0x1A)) {
if (para->dst_image.format ==
G2D_FMT_PYUV411UVC)
bppnum = 4;
else
bppnum = 8;
if (para->dst_image.format ==
G2D_FMT_PYUV420UVC)
addr_val = (__u64)para->dst_image.addr[1] * 8 +
(__u64)((para->dst_image.w *
(scaler_outy/2) +
scaler_outx) * bppnum);
else
addr_val = (__u64)para->dst_image.addr[1] * 8 +
(__u64)((para->dst_image.w *
scaler_outy +
scaler_outx) * bppnum);
reg_val = read_wvalue(G2D_OUTPUT_HADDR_REG);
/* high addr in bits */
reg_val |= ((addr_val>>32)&0xF)<<8;
write_wvalue(G2D_OUTPUT_HADDR_REG, reg_val);
/* low addr in bits */
reg_val = addr_val&0xFFFFFFFF;
write_wvalue(G2D_OUTPUT1_LADDR_REG, reg_val);
write_wvalue(G2D_OUTPUT1_STRIDE_REG,
para->dst_image.w*bppnum);
write_wvalue(G2D_CSC2_CONTROL_REG, 0x1);
}
if ((para->dst_image.format > 0x11) &&
(para->dst_image.format < 0x1D))
write_wvalue(G2D_CSC2_CONTROL_REG, 0x1);
scaler_inx += sinw;
if ((para->flag & G2D_BLT_ROTATE90)) {
scaler_outx += 0x400;
scaler_iny += sinw;
scaler_inx = para->src_rect.x;
} else if ((para->flag & G2D_BLT_ROTATE270)) {
scaler_outx = para->dst_rect.x;
scaler_iny += sinw;
scaler_inx = para->src_rect.x;
} else if ((para->flag & G2D_BLT_ROTATE180)) {
scaler_outy = para->dst_rect.y;
scaler_outx = para->dst_rect.x -
para->dst_image.w;
} else {
scaler_outy = para->dst_rect.y;
scaler_outx += 0x400;
}
/* start */
write_wvalue(G2D_CONTROL_REG, 0x0);
write_wvalue(G2D_CONTROL_REG, 0x303);
result |= g2d_wait_cmd_finish();
if (result != 0)
return result;
}
/* last block */
soutw = para->dst_rect.w - 0x400*cnt;
if ((para->flag & G2D_BLT_ROTATE90) ||
(para->flag & G2D_BLT_ROTATE270))
sinw = para->src_rect.h - sinw*cnt;
else
sinw = para->src_rect.w - sinw*cnt;
/* DMA0 */
addr_val = mixer_get_addr(para->src_image.addr[0],
para->src_image.format, para->src_image.w,
scaler_inx, para->src_rect.y);
if ((para->flag & G2D_BLT_ROTATE90) ||
(para->flag & G2D_BLT_ROTATE270))
addr_val = mixer_get_addr(para->src_image.addr[0],
para->src_image.format,
para->src_image.w,
scaler_inx, scaler_iny);
reg_val = (addr_val>>32)&0xF;/* high addr in bits */
write_wvalue(G2D_DMA_HADDR_REG, reg_val);
reg_val = addr_val&0xFFFFFFFF;/* low addr in bits */
write_wvalue(G2D_DMA0_LADDR_REG, reg_val);
write_wvalue(G2D_DMA0_SIZE_REG,
(sinw - 1) | ((para->src_rect.h - 1)<<16));
if ((para->flag & G2D_BLT_ROTATE90) ||
(para->flag & G2D_BLT_ROTATE270))
write_wvalue(G2D_DMA0_SIZE_REG,
(para->src_rect.w - 1) | ((sinw - 1)<<16));
/* DMA1 pyuv422/420/411uvc */
if ((para->src_image.format > 0x16) &&
(para->src_image.format < 0x1A)) {
if (para->src_image.format ==
G2D_FMT_PYUV411UVC)
bppnum = 4;
else
bppnum = 8;
if (para->src_image.format == G2D_FMT_PYUV420UVC)
addr_val = (__u64)para->src_image.addr[1] * 8 +
(__u64)((para->src_image.w *
(para->src_rect.y/2) +
scaler_inx) * bppnum);
else
addr_val = (__u64)para->src_image.addr[1] * 8 +
(__u64)((para->src_image.w *
para->src_rect.y +
scaler_inx) * bppnum);
reg_val = read_wvalue(G2D_DMA_HADDR_REG);
reg_val |= ((addr_val>>32)&0xF)<<8;/*high addr in bits*/
write_wvalue(G2D_DMA_HADDR_REG, reg_val);
reg_val = addr_val&0xFFFFFFFF;/* low addr in bits */
write_wvalue(G2D_DMA1_LADDR_REG, reg_val);
write_wvalue(G2D_DMA1_STRIDE_REG,
para->src_image.w * bppnum);
if (sinw < 1)
sinw = 1;
write_wvalue(G2D_DMA1_SIZE_REG,
(sinw - 1) | ((para->src_rect.h - 1)<<16));
reg_val = read_wvalue(G2D_DMA1_CONTROL_REG);
reg_val |= (5<<8) | G2D_IDMA_ENABLE;
/* rotate/mirror */
reg_val |= mixer_set_rotate_reg(para->flag);
write_wvalue(G2D_DMA1_CONTROL_REG, reg_val);
}
/* scaler setting */
if (soutw < 1)
soutw = 1;
if ((para->flag & G2D_BLT_ROTATE90) ||
(para->flag & G2D_BLT_ROTATE270)) {
write_wvalue(G2D_SCALER_SIZE_REG,
(para->dst_rect.h - 1) | ((soutw - 1)<<16));
reg_val = (para->src_rect.w/para->dst_rect.h)<<16;
reg_tmp = (para->src_rect.w%para->dst_rect.h);
reg_val |= (reg_tmp<<16)/para->dst_rect.h;
write_wvalue(G2D_SCALER_HFACTOR_REG, reg_val);
reg_val = (sinw/soutw)<<16;
reg_tmp = (sinw%soutw);
reg_val |= (reg_tmp<<16)/soutw;
write_wvalue(G2D_SCALER_VFACTOR_REG, reg_val);
} else {
write_wvalue(G2D_SCALER_SIZE_REG,
(soutw - 1) | ((para->dst_rect.h - 1)<<16));
reg_val = (sinw/soutw)<<16;
reg_tmp = (sinw%soutw);
reg_val |= (reg_tmp<<16)/soutw;
write_wvalue(G2D_SCALER_HFACTOR_REG, reg_val);
reg_val = (para->src_rect.h/para->dst_rect.h)<<16;
reg_tmp = (para->src_rect.h%para->dst_rect.h);
reg_val |= (reg_tmp<<16)/para->dst_rect.h;
write_wvalue(G2D_SCALER_VFACTOR_REG, reg_val);
}
if ((para->flag & G2D_BLT_PIXEL_ALPHA) ||
(para->flag & G2D_BLT_PLANE_ALPHA) ||
(para->flag & G2D_BLT_MULTI_ALPHA) ||
(para->flag & G2D_BLT_SRC_COLORKEY) ||
(para->flag & G2D_BLT_DST_COLORKEY)) {
/* DMA2 pyuv422/420/411uvc */
if ((para->dst_image.format > 0x16) &&
(para->dst_image.format < 0x1A)) {
if (para->dst_image.format == G2D_FMT_PYUV411UVC)
bppnum = 4;
else
bppnum = 8;
if (para->dst_image.format == G2D_FMT_PYUV420UVC)
addr_val = (__u64)para->dst_image.addr[1] * 8 +
(__u64)((para->dst_image.w *
(para->dst_rect.y/2) +
scaler_outx) * bppnum);
else
addr_val = (__u64)para->dst_image.addr[1] * 8 +
(__u64)((para->dst_image.w *
para->dst_rect.y +
scaler_outx)*bppnum);
reg_val = read_wvalue(G2D_DMA_HADDR_REG);
/*high addr in bits*/
reg_val |= ((addr_val>>32)&0xF)<<16;
write_wvalue(G2D_DMA_HADDR_REG, reg_val);
reg_val = addr_val&0xFFFFFFFF;/* low addr in bits */
write_wvalue(G2D_DMA2_LADDR_REG, reg_val);
write_wvalue(G2D_DMA2_STRIDE_REG,
para->dst_image.w*bppnum);
if (soutw < 1)
soutw = 1;
write_wvalue(G2D_DMA2_SIZE_REG,
(soutw - 1) | ((para->dst_rect.h - 1)<<16));
reg_val = read_wvalue(G2D_DMA2_CONTROL_REG);
reg_val |= (5<<8) | G2D_IDMA_ENABLE;
write_wvalue(G2D_DMA2_CONTROL_REG, reg_val);
}
/* DMA3 */
addr_val = mixer_get_addr(para->dst_image.addr[0],
para->dst_image.format, para->dst_image.w,
scaler_outx, para->dst_rect.y);
reg_val = read_wvalue(G2D_DMA_HADDR_REG);
reg_val = reg_val&0xF0FFFFFF;
reg_val |= ((addr_val>>32)&0xF)<<24;/* high addr in bits */
write_wvalue(G2D_DMA_HADDR_REG, reg_val);
reg_val = addr_val&0xFFFFFFFF;/* low addr in bits */
write_wvalue(G2D_DMA3_LADDR_REG, reg_val);
write_wvalue(G2D_DMA3_SIZE_REG,
(soutw - 1) | ((para->dst_rect.h - 1)<<16));
}
/* OUT */
write_wvalue(G2D_OUTPUT_SIZE_REG,
(soutw - 1) | ((para->dst_rect.h - 1)<<16));
if ((para->flag & G2D_BLT_ROTATE90) ||
(para->flag & G2D_BLT_ROTATE270))
addr_val = mixer_get_addr(para->dst_image.addr[0],
para->dst_image.format,
para->dst_image.w,
scaler_outx, scaler_outy);
else
addr_val = mixer_get_addr(para->dst_image.addr[0],
para->dst_image.format, para->dst_image.w,
scaler_outx, para->dst_rect.y);
reg_val = (addr_val>>32)&0xF;/* high addr in bits */
write_wvalue(G2D_OUTPUT_HADDR_REG, reg_val);
reg_val = addr_val&0xFFFFFFFF;/* low addr in bits */
write_wvalue(G2D_OUTPUT0_LADDR_REG, reg_val);
/* OUT1 */
if ((para->dst_image.format > 0x16) &&
(para->dst_image.format < 0x1A)) {
if (para->dst_image.format == G2D_FMT_PYUV411UVC)
bppnum = 4;
else
bppnum = 8;
if (para->dst_image.format == G2D_FMT_PYUV420UVC)
addr_val = (__u64)para->dst_image.addr[1] * 8 +
(__u64)((para->dst_image.w *
(para->dst_rect.y/2) +
scaler_outx)*bppnum);
else
addr_val = (__u64)para->dst_image.addr[1] * 8 +
(__u64)((para->dst_image.w *
para->dst_rect.y +
scaler_outx) * bppnum);
reg_val = read_wvalue(G2D_OUTPUT_HADDR_REG);
/* high addr in bits */
reg_val |= ((addr_val>>32)&0xF)<<8;
write_wvalue(G2D_OUTPUT_HADDR_REG, reg_val);
reg_val = addr_val&0xFFFFFFFF;/* low addr in bits */
write_wvalue(G2D_OUTPUT1_LADDR_REG, reg_val);
write_wvalue(G2D_OUTPUT1_STRIDE_REG,
para->dst_image.w*bppnum);
write_wvalue(G2D_CSC2_CONTROL_REG, 0x1);
}
if ((para->dst_image.format > 0x11) &&
(para->dst_image.format < 0x1D))
write_wvalue(G2D_CSC2_CONTROL_REG, 0x1);
/*scan order*/
write_wvalue(G2D_SCAN_ORDER_REG, (scan_order & 0x3) << 8);
/* start */
write_wvalue(G2D_CONTROL_REG, 0x0);
write_wvalue(G2D_CONTROL_REG, 0x303);
result |= g2d_wait_cmd_finish();
}
/* output width smaller than 1024 pixel width */
else {
addr_val = mixer_get_addr(para->src_image.addr[0],
para->src_image.format, para->src_image.w,
para->src_rect.x, para->src_rect.y);
reg_val = (addr_val>>32)&0xF;/* high addr in bits */
write_wvalue(G2D_DMA_HADDR_REG, reg_val);
reg_val = addr_val&0xFFFFFFFF;/* low addr in bits */
write_wvalue(G2D_DMA0_LADDR_REG, reg_val);
write_wvalue(G2D_DMA0_SIZE_REG,
(para->src_rect.w - 1) | ((para->src_rect.h - 1)<<16));
if ((para->flag & G2D_BLT_ROTATE90) ||
(para->flag & G2D_BLT_ROTATE270)) {
write_wvalue(G2D_SCALER_SIZE_REG,
(para->dst_rect.h - 1) |
((para->dst_rect.w - 1)<<16));
reg_val = (para->src_rect.w/para->dst_rect.h)<<16;
reg_tmp = (para->src_rect.w%para->dst_rect.h);
reg_val |= (reg_tmp<<16)/para->dst_rect.h;
write_wvalue(G2D_SCALER_HFACTOR_REG, reg_val);
reg_val = (para->src_rect.h/para->dst_rect.w)<<16;
reg_tmp = (para->src_rect.h%para->dst_rect.w);
reg_val |= (reg_tmp<<16)/para->dst_rect.w;
write_wvalue(G2D_SCALER_VFACTOR_REG, reg_val);
} else {
write_wvalue(G2D_SCALER_SIZE_REG,
(para->dst_rect.w - 1) |
((para->dst_rect.h - 1)<<16));
reg_val = (para->src_rect.w/para->dst_rect.w)<<16;
reg_tmp = (para->src_rect.w%para->dst_rect.w);
reg_val |= (reg_tmp<<16)/para->dst_rect.w;
write_wvalue(G2D_SCALER_HFACTOR_REG, reg_val);
reg_val = (para->src_rect.h/para->dst_rect.h)<<16;
reg_tmp = (para->src_rect.h%para->dst_rect.h);
reg_val |= (reg_tmp<<16)/para->dst_rect.h;
write_wvalue(G2D_SCALER_VFACTOR_REG, reg_val);
}
/* pyuv422/420/411uvc */
if ((para->src_image.format > 0x16) &&
(para->src_image.format < 0x1A)) {
if (para->src_image.format == G2D_FMT_PYUV411UVC)
bppnum = 4;
else
bppnum = 8;
if (para->src_image.format == G2D_FMT_PYUV420UVC)
addr_val = (__u64)para->src_image.addr[1] * 8 +
(__u64)((para->src_image.w *
(para->src_rect.y/2) +
para->src_rect.x) * bppnum);
else
addr_val = (__u64)para->src_image.addr[1] * 8 +
(__u64)((para->src_image.w *
para->src_rect.y +
para->src_rect.x) * bppnum);
reg_val = read_wvalue(G2D_DMA_HADDR_REG);
/* high addr in bits */
reg_val |= ((addr_val>>32)&0xF)<<8;
write_wvalue(G2D_DMA_HADDR_REG, reg_val);
reg_val = addr_val&0xFFFFFFFF;/* low addr in bits */
write_wvalue(G2D_DMA1_LADDR_REG, reg_val);
write_wvalue(G2D_DMA1_STRIDE_REG,
para->src_image.w*bppnum);
write_wvalue(G2D_DMA1_SIZE_REG,
(para->src_rect.w - 1) |
((para->src_rect.h - 1)<<16));
reg_val = read_wvalue(G2D_DMA1_CONTROL_REG);
reg_val |= (5<<8) | G2D_IDMA_ENABLE;
reg_val |= mixer_set_rotate_reg(para->flag);
write_wvalue(G2D_DMA1_CONTROL_REG, reg_val);
}
if ((para->flag & G2D_BLT_PIXEL_ALPHA) ||
(para->flag & G2D_BLT_PLANE_ALPHA) ||
(para->flag & G2D_BLT_MULTI_ALPHA) ||
(para->flag & G2D_BLT_SRC_COLORKEY) ||
(para->flag & G2D_BLT_DST_COLORKEY)) {
/* pyuv422/420/411uvc */
if ((para->dst_image.format > 0x16) &&
(para->dst_image.format < 0x1A)) {
if (para->dst_image.format == G2D_FMT_PYUV411UVC)
bppnum = 4;
else
bppnum = 8;
if (para->dst_image.format == G2D_FMT_PYUV420UVC)
addr_val = (__u64)para->dst_image.addr[1] * 8 +
(__u64)((para->dst_image.w *
(para->dst_rect.y/2) +
para->dst_rect.x) * bppnum);
else
addr_val = (__u64)para->dst_image.addr[1] * 8 +
(__u64)((para->dst_image.w *
para->dst_rect.y +
para->dst_rect.x) * bppnum);
reg_val = read_wvalue(G2D_DMA_HADDR_REG);
/* high addr in bits */
reg_val |= ((addr_val>>32)&0xF)<<16;
write_wvalue(G2D_DMA_HADDR_REG, reg_val);
reg_val = addr_val&0xFFFFFFFF;/* low addr in bits */
write_wvalue(G2D_DMA2_LADDR_REG, reg_val);
write_wvalue(G2D_DMA2_STRIDE_REG,
para->dst_image.w * bppnum);
write_wvalue(G2D_DMA2_SIZE_REG,
(para->dst_rect.w - 1) |
((para->dst_rect.h - 1)<<16));
reg_val = read_wvalue(G2D_DMA2_CONTROL_REG);
reg_val |= (5<<8) | G2D_IDMA_ENABLE;
write_wvalue(G2D_DMA2_CONTROL_REG, reg_val);
}
addr_val = mixer_get_addr(para->dst_image.addr[0],
para->dst_image.format, para->dst_image.w,
para->dst_rect.x, para->dst_rect.y);
reg_val = read_wvalue(G2D_DMA_HADDR_REG);
reg_val |= ((addr_val>>32)&0xF)<<24;/* high addr in bits */
write_wvalue(G2D_DMA_HADDR_REG, reg_val);
reg_val = addr_val&0xFFFFFFFF;/* low addr in bits */
write_wvalue(G2D_DMA3_LADDR_REG, reg_val);
write_wvalue(G2D_DMA3_SIZE_REG,
(para->dst_rect.w - 1) |
((para->dst_rect.h - 1)<<16));
}
/* output surface is the dst surface */
write_wvalue(G2D_OUTPUT_SIZE_REG,
(para->dst_rect.w - 1) |
((para->dst_rect.h - 1)<<16));
addr_val = mixer_get_addr(para->dst_image.addr[0],
para->dst_image.format, para->dst_image.w,
para->dst_rect.x, para->dst_rect.y);
reg_val = (addr_val>>32)&0xF;/* high addr in bits */
write_wvalue(G2D_OUTPUT_HADDR_REG, reg_val);
reg_val = addr_val&0xFFFFFFFF;/* low addr in bits */
write_wvalue(G2D_OUTPUT0_LADDR_REG, reg_val);
if ((para->dst_image.format > 0x16) &&
(para->dst_image.format < 0x1D)) {
if ((para->dst_image.format == G2D_FMT_PYUV411UVC) ||
(para->dst_image.format == G2D_FMT_PYUV422) ||
(para->dst_image.format == G2D_FMT_PYUV420))
bppnum = 4;
else if (para->dst_image.format == G2D_FMT_PYUV411)
bppnum = 2;
else
bppnum = 8;
if ((para->dst_image.format == G2D_FMT_PYUV420UVC) ||
(para->dst_image.format == G2D_FMT_PYUV420))
addr_val = (__u64)para->dst_image.addr[1] * 8 +
(__u64)((para->dst_image.w *
(para->dst_rect.y/2) +
para->dst_rect.x) * bppnum);
else
addr_val = (__u64)para->dst_image.addr[1] * 8 +
(__u64)((para->dst_image.w *
para->dst_rect.y +
para->dst_rect.x) * bppnum);
reg_val = read_wvalue(G2D_OUTPUT_HADDR_REG);
/* high addr in bits */
reg_val |= ((addr_val>>32)&0xF)<<8;
write_wvalue(G2D_OUTPUT_HADDR_REG, reg_val);
reg_val = addr_val&0xFFFFFFFF;/* low addr in bits */
write_wvalue(G2D_OUTPUT1_LADDR_REG, reg_val);
write_wvalue(G2D_OUTPUT1_STRIDE_REG,
para->dst_image.w * bppnum);
if (para->dst_image.format == G2D_FMT_PYUV420)
addr_val = (__u64)para->dst_image.addr[2] * 8 +
(__u64)((para->dst_image.w *
(para->dst_rect.y/2) +
para->dst_rect.x) * bppnum);
else if ((para->dst_image.format == G2D_FMT_PYUV422) ||
(para->dst_image.format == G2D_FMT_PYUV411))
addr_val = (__u64)para->dst_image.addr[2] * 8 +
(__u64)((para->dst_image.w *
para->dst_rect.y +
para->dst_rect.x) * bppnum);
else
addr_val = 0;
reg_val = read_wvalue(G2D_OUTPUT_HADDR_REG);
/* high addr in bits */
reg_val |= ((addr_val>>32)&0xF)<<16;
write_wvalue(G2D_OUTPUT_HADDR_REG, reg_val);
reg_val = addr_val&0xFFFFFFFF;/* low addr in bits */
write_wvalue(G2D_OUTPUT2_LADDR_REG, reg_val);
write_wvalue(G2D_OUTPUT2_STRIDE_REG,
para->dst_image.w * bppnum);
write_wvalue(G2D_CSC2_CONTROL_REG, 0x1);
}
if ((para->dst_image.format > 0x11) &&
(para->dst_image.format < 0x1D))
write_wvalue(G2D_CSC2_CONTROL_REG, 0x1);
/*scan order*/
write_wvalue(G2D_SCAN_ORDER_REG, (scan_order & 0x3) << 8);
/* start */
write_wvalue(G2D_CONTROL_REG, 0x0);
write_wvalue(G2D_CONTROL_REG, 0x303);
result = g2d_wait_cmd_finish();
}
return result;
}
__u32 mixer_set_palette(g2d_palette *para)
{
__u32 *pdest_end;
__u32 *psrc_cur;
__u32 *pdest_cur;
if (para->size > 0x400)
para->size = 0x400;
psrc_cur = para->pbuffer;
pdest_cur = (__u32 *)(base_addr+G2D_PALETTE_TAB_REG);
pdest_end = pdest_cur + (para->size>>2);
while (pdest_cur < pdest_end)
*(volatile __u32 *)pdest_cur++ = *psrc_cur++;
return 0;
}
__s32 mixer_cmdq(__u32 addr)
{
__s32 result = 0;
write_wvalue(G2D_CONTROL_REG, 0x0);
write_wvalue(G2D_CMDQ_ADDR_REG, addr);
/* start */
write_wvalue(G2D_CMDQ_STS_REG, 0x100);
write_wvalue(G2D_CMDQ_CTL_REG, 0x0);
write_wvalue(G2D_CMDQ_CTL_REG, 0x103);
result = g2d_wait_cmd_finish();
return result;
}
__u32 mixer_premultiply_set(__u32 flag)
{
__u32 reg_val;
reg_val = read_wvalue(G2D_CK_CONTROL_REG);
/* src premultiply, dst non-premultiply,
* dst_c = src_c + dst_c*(1-src_a)/A;A = src_a + dst_a*(1-src_a)
*/
if (flag&G2D_BLT_SRC_PREMULTIPLY) {
reg_val |= (0x3<<6);
write_wvalue(G2D_CK_CONTROL_REG, reg_val);
}
/* src non-premultiply, dst(out) premultiply,
* dst_c = src_c*src_a + dst_c*dst_a(1-src_a);
* A = src_a + dst_a*(1-src_a)
*/
else if (flag&G2D_BLT_DST_PREMULTIPLY) {
reg_val |= (0x7<<5);
write_wvalue(G2D_CK_CONTROL_REG, reg_val);
write_wvalue(G2D_OALPHA_CONTROL_REG, 0xAA);
}
return 0;
}
__u32 mixer_micro_block_set(g2d_blt *para)
{
__u32 reg_val, bppnum;
__u64 addr_val;
if (para->src_image.format > 0x20) {
if ((para->src_image.format == G2D_FMT_PYUV411UVC_MB16) ||
(para->src_image.format == G2D_FMT_PYUV411UVC_MB32) ||
(para->src_image.format == G2D_FMT_PYUV411UVC_MB64) ||
(para->src_image.format == G2D_FMT_PYUV411UVC_MB128))
bppnum = 4;
else
bppnum = 8;
if ((para->src_image.format == G2D_FMT_PYUV420UVC_MB16) ||
(para->src_image.format == G2D_FMT_PYUV420UVC_MB32) ||
(para->src_image.format == G2D_FMT_PYUV420UVC_MB64) ||
(para->src_image.format == G2D_FMT_PYUV420UVC_MB128))
addr_val = (__u64)para->src_image.addr[1] * 8 +
(__u64)((para->src_image.w *
(para->src_rect.y/2) +
para->src_rect.x) * bppnum);
else
addr_val = (__u64)para->src_image.addr[1] * 8 +
(__u64)((para->src_image.w *
para->src_rect.y +
para->src_rect.x) * bppnum);
reg_val = read_wvalue(G2D_DMA_HADDR_REG);
reg_val |= ((addr_val>>32)&0xF)<<8;/* high addr in bits */
write_wvalue(G2D_DMA_HADDR_REG, reg_val);
reg_val = addr_val&0xFFFFFFFF;/* low addr in bits */
write_wvalue(G2D_DMA1_LADDR_REG, reg_val);
write_wvalue(G2D_DMA1_STRIDE_REG, para->src_image.w*bppnum);
write_wvalue(G2D_DMA1_SIZE_REG,
(para->src_rect.w - 1) | ((para->src_rect.h - 1)<<16));
reg_val = read_wvalue(G2D_DMA1_CONTROL_REG);
reg_val |= (5<<8) | G2D_IDMA_ENABLE;
/* rotate/mirror */
reg_val |= mixer_set_rotate_reg(para->flag);
write_wvalue(G2D_DMA1_CONTROL_REG, reg_val);
if (para->src_image.format > 0x23 &&
para->src_image.format < 0x27)
reg_val = 0x29<<17;
else if (para->src_image.format > 0x26 &&
para->src_image.format < 0x2A)
reg_val = 0x32<<17;
else if (para->src_image.format > 0x29 &&
para->src_image.format < 0x2D)
reg_val = 0x3b<<17;
else
reg_val = 0x20<<17;
write_wvalue(G2D_DMA0_CONTROL_REG, (reg_val |
(read_wvalue(G2D_DMA0_CONTROL_REG)&0xff81ffff)));
write_wvalue(G2D_DMA1_CONTROL_REG, (reg_val |
(read_wvalue(G2D_DMA1_CONTROL_REG)&0xff81ffff)));
write_wvalue(G2D_DMA0_MBCTL_REG,
(para->src_rect.y&0xFFFF)<<16|
(para->src_rect.x&0xFFFF));
write_wvalue(G2D_DMA1_MBCTL_REG,
(para->src_rect.y&0xFFFF)<<16|
(para->src_rect.x&0xFFFF));
}
return 0;
}