/* 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; }