/* * Allwinner SoCs g2d driver. * * Copyright (C) 2016 Allwinner. * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any * warranty of any kind, whether express or implied. */ #include "g2d_bsp.h" #include "g2d_regs_v2.h" #include #include 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 g2d_fc_set(__u32 sel, __u32 color_value); __s32 g2d_format_trans(__s32 data_fmt, __s32 pixel_seq); __s32 rgb2Ycbcr_709[12] = { 0x0bb, 0x0275, 0x03f, 0x4200, 0xFFFFFF99, 0xFFFFFEA6, 0x01c2, 0x20200, 0x01c2, 0xFFFFFE67, 0xFFFFFFD7, 0x20200, }; __s32 Ycbcr2rgb_709[12] = { 0x04a8, 0x0, 0x072c, 0xFFFC1F7D, 0x04a8, 0xFFFFFF26, 0xFFFFFDDD, 0x133F8, 0x04a8, 0x0876, 0, 0xFFFB7AA0, }; __s32 lan2coefftab32_full[512] = { 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, /* counter = 1 */ 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, /* counter = 2 */ 0xff053804, 0xff063803, 0xff083801, 0xff093701, 0xff0a3700, 0xff0c3500, 0xff0e34ff, 0xff1033fe, 0xff1232fd, 0xfe1431fd, 0xfe162ffd, 0xfe182dfd, 0xfd1b2cfc, 0xfd1d2afc, 0xfd1f28fc, 0xfd2126fc, 0xfd2323fd, 0xfc2621fd, 0xfc281ffd, 0xfc2a1dfd, 0xfc2c1bfd, 0xfd2d18fe, 0xfd2f16fe, 0xfd3114fe, 0xfd3212ff, 0xfe3310ff, 0xff340eff, 0x00350cff, 0x00360a00, 0x01360900, 0x02370700, 0x03370600, /* counter = 3 */ 0xff083207, 0xff093206, 0xff0a3205, 0xff0c3203, 0xff0d3103, 0xff0e3102, 0xfe113001, 0xfe132f00, 0xfe142e00, 0xfe162dff, 0xfe182bff, 0xfe192aff, 0xfe1b29fe, 0xfe1d27fe, 0xfe1f25fe, 0xfd2124fe, 0xfe2222fe, 0xfe2421fd, 0xfe251ffe, 0xfe271dfe, 0xfe291bfe, 0xff2a19fe, 0xff2b18fe, 0xff2d16fe, 0x002e14fe, 0x002f12ff, 0x013010ff, 0x02300fff, 0x03310dff, 0x04310cff, 0x05310a00, 0x06310900, /* counter = 4 */ 0xff0a2e09, 0xff0b2e08, 0xff0c2e07, 0xff0e2d06, 0xff0f2d05, 0xff102d04, 0xff122c03, 0xfe142c02, 0xfe152b02, 0xfe172a01, 0xfe182901, 0xfe1a2800, 0xfe1b2700, 0xfe1d2500, 0xff1e24ff, 0xfe2023ff, 0xff2121ff, 0xff2320fe, 0xff241eff, 0x00251dfe, 0x00261bff, 0x00281afe, 0x012818ff, 0x012a16ff, 0x022a15ff, 0x032b13ff, 0x032c12ff, 0x052c10ff, 0x052d0fff, 0x062d0d00, 0x072d0c00, 0x082d0b00, /* counter = 5 */ 0xff0c2a0b, 0xff0d2a0a, 0xff0e2a09, 0xff0f2a08, 0xff102a07, 0xff112a06, 0xff132905, 0xff142904, 0xff162803, 0xff172703, 0xff182702, 0xff1a2601, 0xff1b2501, 0xff1c2401, 0xff1e2300, 0xff1f2200, 0x00202000, 0x00211f00, 0x01221d00, 0x01231c00, 0x01251bff, 0x02251aff, 0x032618ff, 0x032717ff, 0x042815ff, 0x052814ff, 0x052913ff, 0x06291100, 0x072a10ff, 0x082a0e00, 0x092a0d00, 0x0a2a0c00, /* counter = 6 */ 0xff0d280c, 0xff0e280b, 0xff0f280a, 0xff102809, 0xff112808, 0xff122708, 0xff142706, 0xff152705, 0xff162605, 0xff172604, 0xff192503, 0xff1a2403, 0x001b2302, 0x001c2202, 0x001d2201, 0x001e2101, 0x011f1f01, 0x01211e00, 0x01221d00, 0x02221c00, 0x02231b00, 0x03241900, 0x04241800, 0x04251700, 0x052616ff, 0x06261400, 0x072713ff, 0x08271100, 0x08271100, 0x09271000, 0x0a280e00, 0x0b280d00, /* counter = 7 */ 0xff0e260d, 0xff0f260c, 0xff10260b, 0xff11260a, 0xff122609, 0xff132608, 0xff142508, 0xff152507, 0x00152506, 0x00172405, 0x00182305, 0x00192304, 0x001b2203, 0x001c2103, 0x011d2002, 0x011d2002, 0x011f1f01, 0x021f1e01, 0x02201d01, 0x03211c00, 0x03221b00, 0x04221a00, 0x04231801, 0x05241700, 0x06241600, 0x07241500, 0x08251300, 0x09251200, 0x09261100, 0x0a261000, 0x0b260f00, 0x0c260e00, /* counter = 8 */ 0xff0e250e, 0xff0f250d, 0xff10250c, 0xff11250b, 0x0011250a, 0x00132409, 0x00142408, 0x00152407, 0x00162307, 0x00172306, 0x00182206, 0x00192205, 0x011a2104, 0x011b2004, 0x011c2003, 0x021c1f03, 0x021e1e02, 0x031e1d02, 0x03201c01, 0x04201b01, 0x04211a01, 0x05221900, 0x05221801, 0x06231700, 0x07231600, 0x07241500, 0x08241400, 0x09241300, 0x0a241200, 0x0b241100, 0x0c241000, 0x0d240f00, /* counter = 9 */ 0x000e240e, 0x000f240d, 0x0010240c, 0x0011240b, 0x0013230a, 0x0013230a, 0x00142309, 0x00152308, 0x00162208, 0x00172207, 0x01182106, 0x01192105, 0x011a2005, 0x021b1f04, 0x021b1f04, 0x021d1e03, 0x031d1d03, 0x031e1d02, 0x041e1c02, 0x041f1b02, 0x05201a01, 0x05211901, 0x06211801, 0x07221700, 0x07221601, 0x08231500, 0x09231400, 0x0a231300, 0x0a231300, 0x0b231200, 0x0c231100, 0x0d231000, /* counter = 10 */ 0x000f220f, 0x0010220e, 0x0011220d, 0x0012220c, 0x0013220b, 0x0013220b, 0x0015210a, 0x0015210a, 0x01162108, 0x01172008, 0x01182007, 0x02191f06, 0x02191f06, 0x021a1e06, 0x031a1e05, 0x031c1d04, 0x041c1c04, 0x041d1c03, 0x051d1b03, 0x051e1a03, 0x061f1902, 0x061f1902, 0x07201801, 0x08201701, 0x08211601, 0x09211501, 0x0a211500, 0x0b211400, 0x0b221300, 0x0c221200, 0x0d221100, 0x0e221000, /* counter = 11 */ 0x0010210f, 0x0011210e, 0x0011210e, 0x0012210d, 0x0013210c, 0x0014200c, 0x0114200b, 0x0115200a, 0x01161f0a, 0x01171f09, 0x02171f08, 0x02181e08, 0x03181e07, 0x031a1d06, 0x031a1d06, 0x041b1c05, 0x041c1c04, 0x051c1b04, 0x051d1a04, 0x061d1a03, 0x071d1903, 0x071e1803, 0x081e1802, 0x081f1702, 0x091f1602, 0x0a201501, 0x0b1f1501, 0x0b201401, 0x0c211300, 0x0d211200, 0x0e201200, 0x0e211100, /* counter = 12 */ 0x00102010, 0x0011200f, 0x0012200e, 0x0013200d, 0x0013200d, 0x01141f0c, 0x01151f0b, 0x01151f0b, 0x01161f0a, 0x02171e09, 0x02171e09, 0x03181d08, 0x03191d07, 0x03191d07, 0x041a1c06, 0x041b1c05, 0x051b1b05, 0x051c1b04, 0x061c1a04, 0x071d1903, 0x071d1903, 0x081d1803, 0x081e1703, 0x091e1702, 0x0a1f1601, 0x0a1f1502, 0x0b1f1501, 0x0c1f1401, 0x0d201300, 0x0d201300, 0x0e201200, 0x0f201100, /* counter = 13 */ 0x00102010, 0x0011200f, 0x00121f0f, 0x00131f0e, 0x00141f0d, 0x01141f0c, 0x01141f0c, 0x01151e0c, 0x02161e0a, 0x02171e09, 0x03171d09, 0x03181d08, 0x03181d08, 0x04191c07, 0x041a1c06, 0x051a1b06, 0x051b1b05, 0x061b1a05, 0x061c1a04, 0x071c1904, 0x081c1903, 0x081d1803, 0x091d1703, 0x091e1702, 0x0a1e1602, 0x0b1e1502, 0x0c1e1501, 0x0c1f1401, 0x0d1f1400, 0x0e1f1300, 0x0e1f1201, 0x0f1f1200, /* counter = 14 */ 0x00111e11, 0x00121e10, 0x00131e0f, 0x00131e0f, 0x01131e0e, 0x01141d0e, 0x02151d0c, 0x02151d0c, 0x02161d0b, 0x03161c0b, 0x03171c0a, 0x04171c09, 0x04181b09, 0x05181b08, 0x05191b07, 0x06191a07, 0x061a1a06, 0x071a1906, 0x071b1905, 0x081b1805, 0x091b1804, 0x091c1704, 0x0a1c1703, 0x0a1c1604, 0x0b1d1602, 0x0c1d1502, 0x0c1d1502, 0x0d1d1402, 0x0e1d1401, 0x0e1e1301, 0x0f1e1300, 0x101e1200, /* counter = 15 */ 0x00111e11, 0x00121e10, 0x00131d10, 0x01131d0f, 0x01141d0e, 0x01141d0e, 0x02151c0d, 0x02151c0d, 0x03161c0b, 0x03161c0b, 0x04171b0a, 0x04171b0a, 0x05171b09, 0x05181a09, 0x06181a08, 0x06191a07, 0x07191907, 0x071a1906, 0x081a1806, 0x081a1806, 0x091a1805, 0x0a1b1704, 0x0a1b1704, 0x0b1c1603, 0x0b1c1603, 0x0c1c1503, 0x0d1c1502, 0x0d1d1402, 0x0e1d1401, 0x0f1d1301, 0x0f1d1301, 0x101e1200, /* counter = 16 */ }; __s32 linearcoefftab32[32] = { 0x00004000, 0x00023e00, 0x00043c00, 0x00063a00, 0x00083800, 0x000a3600, 0x000c3400, 0x000e3200, 0x00103000, 0x00122e00, 0x00142c00, 0x00162a00, 0x00182800, 0x001a2600, 0x001c2400, 0x001e2200, 0x00202000, 0x00221e00, 0x00241c00, 0x00261a00, 0x00281800, 0x002a1600, 0x002c1400, 0x002e1200, 0x00301000, 0x00320e00, 0x00340c00, 0x00360a00, 0x00380800, 0x003a0600, 0x003c0400, 0x003e0200, }; __s32 g2d_bsp_open(void) { write_wvalue(G2D_SCLK_GATE, 0x3); write_wvalue(G2D_HCLK_GATE, 0x3); write_wvalue(G2D_AHB_RESET, 0x3); return 0; } __s32 g2d_bsp_close(void) { write_wvalue(G2D_AHB_RESET, 0x0); write_wvalue(G2D_HCLK_GATE, 0x0); write_wvalue(G2D_SCLK_GATE, 0x0); return 0; } __s32 g2d_bsp_reset(void) { write_wvalue(G2D_AHB_RESET, 0x0); write_wvalue(G2D_AHB_RESET, 0x3); return 0; } __s32 g2d_mixer_reset(void) { __u32 reg_val; reg_val = read_wvalue(G2D_AHB_RESET); write_wvalue(G2D_AHB_RESET, reg_val & 0xfffffffe); write_wvalue(G2D_AHB_RESET, reg_val & 0xffffffff); return 0; } __s32 g2d_rot_reset(void) { __u32 reg_val; reg_val = read_wvalue(G2D_AHB_RESET); write_wvalue(G2D_AHB_RESET, reg_val & 0xfffffffd); write_wvalue(G2D_AHB_RESET, reg_val & 0xffffffff); return 0; } __s32 g2d_scan_order_fun(__u32 scan_order) { __u32 tmp; tmp = read_wvalue(G2D_MIXER_CTL); tmp |= ((scan_order >> 24) & 0xf0); write_wvalue(G2D_MIXER_CTL, tmp); return 0; } /** * G2D IRQ query funct * if the mission finish IRQ flag was set to 1, then clear the flag * and return 1 * if the IRQ was set to 0, then return 0 */ __s32 mixer_irq_query(void) { __u32 tmp; tmp = read_wvalue(G2D_MIXER_INT); if (tmp & 0x1) { write_wvalue(G2D_MIXER_INT, tmp); return 0; } return -1; } /** * G2D IRQ query funct * if the mission finish IRQ flag was set to 1, then clear the flag * and return 1 * if the IRQ was set to 0, then return 0 */ __s32 rot_irq_query(void) { __u32 tmp; tmp = read_wvalue(ROT_INT); if (tmp & 0x1) { write_wvalue(ROT_INT, tmp); return 0; } return -1; } __s32 mixer_irq_enable(void) { write_wvalue(G2D_MIXER_INT, 0x10); return 0; } __s32 rot_irq_enable(void) { write_wvalue(ROT_INT, 0x10000); return 0; } __s32 g2d_irq_disable(void) { write_wvalue(G2D_MIXER_INT, 0x0); return 0; } __s32 rot_irq_disable(void) { write_wvalue(ROT_INT, 0x0); return 0; } __s32 g2d_sclk_div(__u32 div) { __u32 reg_val; reg_val = read_wvalue(G2D_SCLK_DIV); reg_val &= 0xfffffff0; reg_val |= (div & 0xf); write_wvalue(G2D_SCLK_DIV, reg_val); return 0; } __s32 rot_sclk_div(__u32 div) { __u32 reg_val; reg_val = read_wvalue(G2D_SCLK_DIV); reg_val &= 0xffffff0f; reg_val |= (div & 0xf) << 4; write_wvalue(G2D_SCLK_DIV, reg_val); return 0; } __s32 porter_duff(__u32 cmd) { switch (cmd) { case G2D_BLD_CLEAR: write_wvalue(BLD_CTL, 0x00000000); break; case G2D_BLD_COPY: write_wvalue(BLD_CTL, 0x00010001); break; case G2D_BLD_DST: write_wvalue(BLD_CTL, 0x01000100); break; case G2D_BLD_SRCOVER: write_wvalue(BLD_CTL, 0x03010301); break; case G2D_BLD_DSTOVER: write_wvalue(BLD_CTL, 0x01030103); break; case G2D_BLD_SRCIN: write_wvalue(BLD_CTL, 0x00020002); break; case G2D_BLD_DSTIN: write_wvalue(BLD_CTL, 0x02000200); break; case G2D_BLD_SRCOUT: write_wvalue(BLD_CTL, 0x00030003); break; case G2D_BLD_DSTOUT: write_wvalue(BLD_CTL, 0x03000300); break; case G2D_BLD_SRCATOP: write_wvalue(BLD_CTL, 0x03020302); break; case G2D_BLD_DSTATOP: write_wvalue(BLD_CTL, 0x02030203); break; case G2D_BLD_XOR: write_wvalue(BLD_CTL, 0x03030303); break; default: write_wvalue(BLD_CTL, 0x03010301); } return 0; } /** * @csc_no: CSC ID, G2D support three CSC, * -1 will return to indicate inappropriate CSC number. * @csc_sel: CSC format, G2D support the ITU-R 601. ITU-R 709. standard trans- * form between RGB and YUV colorspace. */ __s32 g2d_csc_reg_set(__u32 csc_no, g2d_csc_sel csc_sel) { __u32 i; __u32 csc_base_addr; __u32 tmp; switch (csc_no) { case 0: csc_base_addr = G2D_BLD + 0x110; tmp = read_wvalue(BLD_CSC_CTL); tmp |= 0x1; write_wvalue(BLD_CSC_CTL, tmp); break; case 1: csc_base_addr = G2D_BLD + 0x140; tmp = read_wvalue(BLD_CSC_CTL); tmp |= 0x1 << 1; write_wvalue(BLD_CSC_CTL, tmp); break; case 2: csc_base_addr = G2D_BLD + 0x170; tmp = read_wvalue(BLD_CSC_CTL); tmp |= 0x1 << 2; write_wvalue(BLD_CSC_CTL, tmp); break; default: /* __wrn("sel wrong csc no.\n"); */ return -1; } switch (csc_sel) { case G2D_RGB2YUV_709: for (i = 0; i < 12; i++) write_wvalue(csc_base_addr + (i << 2), rgb2Ycbcr_709[i]); break; case G2D_YUV2RGB_709: for (i = 0; i < 12; i++) write_wvalue(csc_base_addr + (i << 2), Ycbcr2rgb_709[i]); break; case G2D_RGB2YUV_601: for (i = 0; i < 12; i++) ; /* write_wvalue(csc_base_addr + (i<<2), */ /* rgb2Ycbcr_601[i]); */ break; case G2D_YUV2RGB_601: for (i = 0; i < 12; i++) ; /* write_wvalue(csc_base_addr + (i<<2), */ /* Ycbcr2rgb_601[i]); */ break; default: /* __wrn("wrong csc standard\n"); */ return -2; } return 0; } /** * set colorkey para. */ __s32 ck_para_set(g2d_ck *para) { __u32 tmp = 0x0; if (para->match_rule) tmp = 0x7; write_wvalue(BLD_KEY_CON, tmp); write_wvalue(BLD_KEY_MAX, para->max_color & 0x00ffffff); write_wvalue(BLD_KEY_MIN, para->min_color & 0x00ffffff); return 0; } /** */ __s32 g2d_byte_cal(__u32 format, __u32 *ycnt, __u32 *ucnt, __u32 *vcnt) { *ycnt = 0; *ucnt = 0; *vcnt = 0; if (format <= G2D_FORMAT_BGRX8888) *ycnt = 4; else if (format <= G2D_FORMAT_BGR888) *ycnt = 3; else if (format <= G2D_FORMAT_BGRA5551) *ycnt = 2; else if (format <= G2D_FORMAT_BGRA1010102) *ycnt = 4; else if (format <= 0x23) { *ycnt = 2; } else if (format <= 0x25) { *ycnt = 1; *ucnt = 2; } else if (format == 0x26) { *ycnt = 1; *ucnt = 1; *vcnt = 1; } else if (format <= 0x29) { *ycnt = 1; *ucnt = 2; } else if (format == 0x2a) { *ycnt = 1; *ucnt = 1; *vcnt = 1; } else if (format <= 0x2d) { *ycnt = 1; *ucnt = 2; } else if (format == 0x2e) { *ycnt = 1; *ucnt = 1; *vcnt = 1; } else if (format == 0x30) *ycnt = 1; else if (format <= 0x36) { *ycnt = 2; *ucnt = 4; } else if (format <= 0x39) *ycnt = 6; return 0; } /** */ __u32 cal_align(__u32 width, __u32 align) { switch (align) { case 0: return width; case 8: return (width + 7) >> 3 << 3; case 16: return (width + 15) >> 4 << 4; case 32: return (width + 31) >> 5 << 5; case 64: return (width + 63) >> 6 << 6; case 128: return (width + 127) >> 7 << 7; default: return (width + 31) >> 5 << 5; } } /** * @sel:layer no. */ __s32 g2d_vlayer_set(__u32 sel, g2d_image_enh *image) { unsigned long long addr0, addr1, addr2; __u32 tmp; __u32 ycnt, ucnt, vcnt; __u32 pitch0, pitch1, pitch2; __u32 ch, cw, cy, cx; switch (sel) { case 0: /* base_addr = G2D_V0; */ break; default: return -1; } tmp = ((image->alpha & 0xff) << 24); if (image->bpremul) tmp |= (0x1 << 17); tmp |= (image->format << 8); tmp |= (image->mode << 1); tmp |= 1; write_wvalue(V0_ATTCTL, tmp); tmp = (((image->clip_rect.h == 0 ? 0 : image->clip_rect.h - 1) & 0x1fff) << 16) | ((image->clip_rect.w == 0 ? 0 : image->clip_rect.w - 1) & 0x1fff); write_wvalue(V0_MBSIZE, tmp); /* offset is set to 0, ovl size is set to layer size */ write_wvalue(V0_SIZE, tmp); write_wvalue(V0_COOR, 0); if ((image->format >= G2D_FORMAT_YUV422UVC_V1U1V0U0) && (image->format <= G2D_FORMAT_YUV422_PLANAR)) { cw = image->width >> 1; ch = image->height; cx = image->clip_rect.x >> 1; cy = image->clip_rect.y; } else if ((image->format >= G2D_FORMAT_YUV420UVC_V1U1V0U0) && (image->format <= G2D_FORMAT_YUV420_PLANAR)) { cw = image->width >> 1; ch = image->height >> 1; cx = image->clip_rect.x >> 1; cy = image->clip_rect.y >> 1; } else if ((image->format >= G2D_FORMAT_YUV411UVC_V1U1V0U0) && (image->format <= G2D_FORMAT_YUV411_PLANAR)) { cw = image->width >> 2; ch = image->height; cx = image->clip_rect.x >> 2; cy = image->clip_rect.y; } else { cw = 0; ch = 0; cx = 0; cy = 0; } g2d_byte_cal(image->format, &ycnt, &ucnt, &vcnt); pitch0 = cal_align(ycnt * image->width, image->align[0]); write_wvalue(V0_PITCH0, pitch0); pitch1 = cal_align(ucnt * cw, image->align[1]); write_wvalue(V0_PITCH1, pitch1); pitch2 = cal_align(vcnt * cw, image->align[2]); write_wvalue(V0_PITCH2, pitch2); pr_info("video chn set pitch ok!\n"); G2D_INFO_MSG("VInPITCH: %d, %d, %d\n", pitch0, pitch1, pitch2); G2D_INFO_MSG("VInAddrB: 0x%x, 0x%x, 0x%x\n", image->laddr[0], image->laddr[1], image->laddr[2]); addr0 = image->laddr[0] + ((__u64) image->haddr[0] << 32) + pitch0 * image->clip_rect.y + ycnt * image->clip_rect.x; write_wvalue(V0_LADD0, addr0 & 0xffffffff); addr1 = image->laddr[1] + ((__u64) image->haddr[1] << 32) + pitch1 * cy + ucnt * cx; write_wvalue(V0_LADD1, addr1 & 0xffffffff); addr2 = image->laddr[2] + ((__u64) image->haddr[2] << 32) + pitch2 * cy + vcnt * cx; write_wvalue(V0_LADD2, addr2 & 0xffffffff); tmp = ((addr0 >> 32) & 0xff) | ((addr1 >> 32) & 0xff) << 8 | ((addr2 >> 32) & 0xff) << 16; write_wvalue(V0_HADD, tmp); G2D_INFO_MSG("VInAddrA: 0x%llx, 0x%llx, 0x%llx\n", addr0, addr1, addr2); if (image->bbuff == 0) g2d_fc_set((sel + VI_LAYER_NUMBER), image->color); return 0; } __s32 g2d_uilayer_set(__u32 sel, g2d_image_enh *img) { __u64 addr0; __u32 base_addr_u, tmp; __u32 ycnt, ucnt, vcnt; __u32 pitch0; switch (sel) { case 0: base_addr_u = G2D_UI0; break; case 1: base_addr_u = G2D_UI1; break; case 2: base_addr_u = G2D_UI2; break; default: return -1; } tmp = (img->alpha & 0xff) << 24; if (img->bpremul) tmp |= 0x1 << 17; tmp |= img->format << 8; tmp |= img->mode << 1; tmp |= 1; write_wvalue(base_addr_u, tmp); tmp = (((img->clip_rect.h == 0 ? 0 : img->clip_rect.h - 1) & 0x1fff) << 16) | ((img->clip_rect.w == 0 ? 0 : img->clip_rect.w - 1) & 0x1fff); write_wvalue(base_addr_u + 0x4, tmp); write_wvalue(base_addr_u + 0x1C, tmp); write_wvalue(base_addr_u + 0x8, 0); g2d_byte_cal(img->format, &ycnt, &ucnt, &vcnt); pitch0 = cal_align(ycnt * img->width, img->align[0]); write_wvalue(base_addr_u + 0xC, pitch0); addr0 = img->laddr[0] + ((__u64) img->haddr[0] << 32) + pitch0 * img->clip_rect.y + ycnt * img->clip_rect.x; write_wvalue(base_addr_u + 0x10, addr0 & 0xffffffff); write_wvalue(base_addr_u + 0x18, (addr0 >> 32) & 0xff); if (img->bbuff == 0) g2d_fc_set((sel + VI_LAYER_NUMBER), img->color); return 0; } __s32 g2d_wb_set(g2d_image_enh *image) { __u64 addr0, addr1, addr2; __u32 tmp; __u32 ycnt, ucnt, vcnt; __u32 pitch0, pitch1, pitch2; __u32 ch, cw, cy, cx; write_wvalue(WB_ATT, image->format); tmp = (((image->clip_rect.h == 0 ? 0 : image->clip_rect.h - 1) & 0x1fff) << 16) | ((image->clip_rect.w == 0 ? 0 : image->clip_rect.w - 1) & 0x1fff); write_wvalue(WB_SIZE, tmp); /*write to the bld out reg */ G2D_INFO_MSG("BLD_CH_OSIZE W: 0x%x\n", image->clip_rect.w); G2D_INFO_MSG("BLD_CH_OSIZE H: 0x%x\n", image->clip_rect.h); write_wvalue(BLD_SIZE, tmp); /* set outdata premul */ tmp = read_wvalue(BLD_OUT_COLOR); if (image->bpremul) write_wvalue(BLD_OUT_COLOR, tmp | 0x1); else write_wvalue(BLD_OUT_COLOR, tmp & 0x2); if ((image->format >= G2D_FORMAT_YUV422UVC_V1U1V0U0) && (image->format <= G2D_FORMAT_YUV422_PLANAR)) { cw = image->width >> 1; ch = image->height; cx = image->clip_rect.x >> 1; cy = image->clip_rect.y; } else if ((image->format >= G2D_FORMAT_YUV420UVC_V1U1V0U0) && (image->format <= G2D_FORMAT_YUV420_PLANAR)) { cw = image->width >> 1; ch = image->height >> 1; cx = image->clip_rect.x >> 1; cy = image->clip_rect.y >> 1; } else if ((image->format >= G2D_FORMAT_YUV411UVC_V1U1V0U0) && (image->format <= G2D_FORMAT_YUV411_PLANAR)) { cw = image->width >> 2; ch = image->height; cx = image->clip_rect.x >> 2; cy = image->clip_rect.y; } else { cw = 0; ch = 0; cx = 0; cy = 0; } g2d_byte_cal(image->format, &ycnt, &ucnt, &vcnt); pitch0 = cal_align(ycnt * image->width, image->align[0]); write_wvalue(WB_PITCH0, pitch0); pitch1 = cal_align(ucnt * cw, image->align[1]); write_wvalue(WB_PITCH1, pitch1); pitch2 = cal_align(vcnt * cw, image->align[2]); write_wvalue(WB_PITCH2, pitch2); addr0 = image->laddr[0] + ((__u64) image->haddr[0] << 32) + pitch0 * image->clip_rect.y + ycnt * image->clip_rect.x; write_wvalue(WB_LADD0, addr0 & 0xffffffff); write_wvalue(WB_HADD0, (addr0 >> 32) & 0xff); addr1 = image->laddr[1] + ((__u64) image->haddr[1] << 32) + pitch1 * cy + ucnt * cx; write_wvalue(WB_LADD1, addr1 & 0xffffffff); write_wvalue(WB_HADD1, (addr1 >> 32) & 0xff); addr2 = image->laddr[2] + ((__u64) image->haddr[2] << 32) + pitch2 * cy + vcnt * cx; write_wvalue(WB_LADD2, addr2 & 0xffffffff); write_wvalue(WB_HADD2, (addr2 >> 32) & 0xff); G2D_INFO_MSG("WbAddr: 0x%llx, 0x%llx, 0x%llx\n", addr0, addr1, addr2); return 0; } /** * fillcolor set * @sel:layer_no, 0--Layer Video,1--Layer UI0,2--Layer UI1,3--Layer UI2 * @color_value:fill color value */ __s32 g2d_fc_set(__u32 sel, __u32 color_value) { __u32 tmp; G2D_INFO_MSG("FILLCOLOR: sel: %d, color: 0x%x\n", sel, color_value); if (sel == 0) { /* Layer Video */ tmp = read_wvalue(V0_ATTCTL); tmp |= (0x1 << 4); write_wvalue(V0_ATTCTL, tmp); write_wvalue(V0_FILLC, color_value); } if (sel == 1) { /* Layer UI0 */ tmp = read_wvalue(UI0_ATTR); tmp |= (0x1 << 4); write_wvalue(UI0_ATTR, tmp); write_wvalue(UI0_FILLC, color_value); } if (sel == 2) { /* Layer UI1 */ tmp = read_wvalue(UI1_ATTR); tmp |= (0x1 << 4); write_wvalue(UI1_ATTR, tmp); write_wvalue(UI1_FILLC, color_value); } if (sel == 3) { /* Layer UI2 */ tmp = read_wvalue(UI2_ATTR); tmp |= (0x1 << 4); write_wvalue(UI2_ATTR, tmp); write_wvalue(UI2_FILLC, color_value); } return 0; } /** * ROP2 cmd register set * Index0 is selected * dst mapping ch0' * src mapping ch1' */ __s32 g2d_rop2_set(__u32 rop_cmd) { if (rop_cmd == G2D_BLT_BLACKNESS) { /* blackness */ /* tmpue = 0x1<<18; */ write_wvalue(ROP_INDEX0, 0x40000); } else if (rop_cmd == G2D_BLT_NOTMERGEPEN) { /* ~(dst | src) */ /* tmpue = (0x1<<6) | (0x1<<10) | (0x2<<11) | (0x1<<18); */ write_wvalue(ROP_INDEX0, 0x41440); } else if (rop_cmd == G2D_BLT_MASKNOTPEN) { /* ~src&dst */ /* tmpue = (0x1<<4) | (0x0<<10) | (0x2<<11) | (0x1<<18); */ write_wvalue(ROP_INDEX0, 0x41010); } else if (rop_cmd == G2D_BLT_NOTCOPYPEN) { /* ~src */ /* tmpue = (0x1<<4) | (0x2<<6) | (0x2<<11) | * (0x1<<18) | (0x1<<17); */ write_wvalue(ROP_INDEX0, 0x61090); } else if (rop_cmd == G2D_BLT_MASKPENNOT) { /* src&~dst */ /* tmpue = (0x1<<3) | (0x0<<10) | (0x2<<11) | (0x1<<18); */ write_wvalue(ROP_INDEX0, 0x41008); } else if (rop_cmd == G2D_BLT_NOT) { /* ~dst */ /* tmpue = (0x1<<3) | (0x2<<6) | (0x2<<11) | * (0x1<<18) | (0x1<<16); */ write_wvalue(ROP_INDEX0, 0x51088); } else if (rop_cmd == G2D_BLT_XORPEN) { /* src xor dst */ /* tmpue = (0x2<<6) | (0x2<<11) | (0x1<<18); */ write_wvalue(ROP_INDEX0, 0x41080); } else if (rop_cmd == G2D_BLT_NOTMASKPEN) { /* ~(src & dst) */ /* tmpue = (0x0<<6) | (0x1<<10) | (0x2<<11) | (0x1<<18); */ write_wvalue(ROP_INDEX0, 0x41400); } else if (rop_cmd == G2D_BLT_MASKPEN) { /* src&dst */ /* tmpue = (0x0<<6) | (0x2<<11) | (0x1<<18); */ write_wvalue(ROP_INDEX0, 0x41000); } else if (rop_cmd == G2D_BLT_NOTXORPEN) { /* ~(src xor dst) */ /* tmpue = (0x2<<6) | (0x1<<10) | (0x2<<11) | (0x1<<18); */ write_wvalue(ROP_INDEX0, 0x41480); } else if (rop_cmd == G2D_BLT_NOP) { /* dst */ /* tmpue = (0x2<<6) | (0x2<<11) | (0x1<<18) | (0x1<<16); */ write_wvalue(ROP_INDEX0, 0x51080); } else if (rop_cmd == G2D_BLT_MERGENOTPEN) { /* ~dst or src */ /* tmpue = (0x1<<3)| (0x1<<6) | (0x2<<11) | (0x1<<18) */ /* write_wvalue(ROP_INDEX0, 0x40A20); */ write_wvalue(ROP_INDEX0, 0x41048); } else if (rop_cmd == G2D_BLT_COPYPEN) { /* src */ /* tmpue = (0x2<<6) | (0x2<<11) | (0x1<<18) | (0x1<<17); */ write_wvalue(ROP_INDEX0, 0x61080); } else if (rop_cmd == G2D_BLT_MERGEPENNOT) { /* src or ~dst */ /* tmpue = (0x1<<3)| (0x1<<6) | (0x2<<11) | (0x1<<18) */ write_wvalue(ROP_INDEX0, 0x41048); } else if (rop_cmd == G2D_BLT_MERGEPEN) { /* src or dst */ /* tmpue = (0x1<<6) | (0x1<<18) | (0x2<<11); */ write_wvalue(ROP_INDEX0, 0x41040); } else if (rop_cmd == G2D_BLT_WHITENESS) { /* whiteness */ /* tmpue = (0x1<<18) | (0x1<<15); */ write_wvalue(ROP_INDEX0, 0x48000); } else return -1; return 0; } /** * ROP3 cmd register set * dst mapping ch0' * src mapping ch1' * ptn mapping ch2' * -1 return meaning that the operate is not supported by now */ __s32 g2d_rop3_set(__u32 sel, __u32 rop3_cmd) { __u32 addr; if (sel == 0) addr = ROP_INDEX0; else if (sel == 1) addr = ROP_INDEX1; else return -1; if (rop3_cmd == G2D_ROP3_BLACKNESS) { /* blackness */ /* 0x1<<18; */ write_wvalue(addr, 0x40000); } else if (rop3_cmd == G2D_ROP3_NOTSRCERASE) { /* (~src) AND (~dst) */ /* (0x1<<3) | (0x1<<4) | (0x1<<18) | (0x2<<11); */ write_wvalue(addr, 0x41018); } else if (rop3_cmd == G2D_ROP3_NOTSRCCOPY) { /* ~src */ /* (0x1<<4) | (0x2<<6) | (0x2<<11) | (0x1<<18) | (0x1<<16); */ write_wvalue(addr, 0x51090); } else if (rop3_cmd == G2D_ROP3_SRCERASE) { /* src AND ~dst */ /* (0x1<<3) | (0x0<<6) | (0x2<<11) | (0x1<<18); */ write_wvalue(addr, 0x41008); } else if (rop3_cmd == G2D_ROP3_DSTINVERT) { /* ~dst */ /* (0x1<<3) | (0x2<<6) | (0x2<<11) | (0x1<<18) | (0x1<<17); */ write_wvalue(addr, 0x61088); } else if (rop3_cmd == G2D_ROP3_PATINVERT) { /* ptn XOR dst */ /* (0x2<<6) | (0x2<<11) | (0x1<<17) */ write_wvalue(addr, 0x21080); } else if (rop3_cmd == G2D_ROP3_SRCINVERT) { /* src XOR dst */ /* (0x2<<6) | (0x2<<11) | (0x1<<18); */ write_wvalue(addr, 0x41080); } else if (rop3_cmd == G2D_ROP3_SRCAND) { /* src AND dst */ /* (0x0<<6) | (0x2<<11) | (0x1<<18); */ write_wvalue(addr, 0x41000); } else if (rop3_cmd == G2D_ROP3_MERGEPAINT) { /* ~src OR dst */ /* (0x1<<4) | (0x1<<6) | (0x2<<11) | (0x1<<18); */ write_wvalue(addr, 0x41050); } else if (rop3_cmd == G2D_ROP3_MERGECOPY) { /* src AND pattern */ /* (0x2<<6) | (0x1<<16) */ write_wvalue(addr, 0x10080); } else if (rop3_cmd == G2D_ROP3_SRCCOPY) { /* src */ /* (0x2<<6) | (0x2<<11) | (0x1<<18) | (0x1<<16); */ write_wvalue(addr, 0x51080); } else if (rop3_cmd == G2D_ROP3_SRCPAINT) { /* src OR dst */ /* (0x1<<6) | (0x2<<11) | (0x1<<18); */ write_wvalue(addr, 0x41040); } else if (rop3_cmd == G2D_ROP3_PATCOPY) { /* ptn */ /* (0x1<<16) | (0x1<<17) | (0x2)<<11 */ write_wvalue(addr, 0x31000); } else if (rop3_cmd == G2D_ROP3_PATPAINT) { /* DPSnoo */ /* (0x1<<3) | (0x1<<6) | (0x1<<11) */ write_wvalue(addr, 0x848); } else if (rop3_cmd == G2D_ROP3_WHITENESS) { /* whiteness */ write_wvalue(addr, 0x48000); } else return -1; return 0; } /** * background color set */ __s32 g2d_bk_set(__u32 color) { write_wvalue(BLD_BK_COLOR, color & 0xffffffff); return 0; } /** * function : g2d_vsu_calc_fir_coef(unsigned int step) * description : set fir coefficients * parameters : * step * return : * offset (in word) of coefficient table */ static __u32 g2d_vsu_calc_fir_coef(__u32 step) { __u32 pt_coef; __u32 scale_ratio, int_part, float_part, fir_coef_ofst; scale_ratio = step >> (VSU_PHASE_FRAC_BITWIDTH - 3); int_part = scale_ratio >> 3; float_part = scale_ratio & 0x7; fir_coef_ofst = (int_part == 0) ? VSU_ZOOM0_SIZE : (int_part == 1) ? VSU_ZOOM0_SIZE + float_part : (int_part == 2) ? VSU_ZOOM0_SIZE + VSU_ZOOM1_SIZE + (float_part >> 1) : (int_part == 3) ? VSU_ZOOM0_SIZE + VSU_ZOOM1_SIZE + VSU_ZOOM2_SIZE : (int_part == 4) ? VSU_ZOOM0_SIZE + VSU_ZOOM1_SIZE + VSU_ZOOM2_SIZE + VSU_ZOOM3_SIZE : VSU_ZOOM0_SIZE + VSU_ZOOM1_SIZE + VSU_ZOOM2_SIZE + VSU_ZOOM3_SIZE + VSU_ZOOM4_SIZE; pt_coef = fir_coef_ofst * VSU_PHASE_NUM; return pt_coef; } __s32 g2d_rop_by_pass(__u32 sel) { if (sel == 0) write_wvalue(ROP_CTL, 0xF0); else if (sel == 1) write_wvalue(ROP_CTL, 0x55F0); else if (sel == 2) write_wvalue(ROP_CTL, 0xAAF0); else return -1; return 0; } __s32 g2d_vsu_para_set(__u32 fmt, __u32 in_w, __u32 in_h, __u32 out_w, __u32 out_h, __u8 alpha) { __u32 i; __u64 tmp, temp; __u32 yhstep, yvstep; __u32 incw, inch; __u32 yhcoef_offset, yvcoef_offset, chcoef_offset; __u32 format; if (fmt > G2D_FORMAT_IYUV422_Y1U0Y0V0) write_wvalue(VS_CTRL, 0x10101); else write_wvalue(VS_CTRL, 0x00000101); tmp = ((out_h - 1) << 16) | (out_w - 1); write_wvalue(VS_OUT_SIZE, tmp); write_wvalue(VS_GLB_ALPHA, alpha & 0xff); write_wvalue(VS_Y_SIZE, ((in_h - 1) << 16) | (in_w - 1)); temp = in_w << VSU_PHASE_FRAC_BITWIDTH; if (out_w) do_div(temp, out_w); /* temp = temp/out_w; */ else temp = 0; yhstep = temp; write_wvalue(VS_Y_HSTEP, yhstep << 1); temp = in_h << VSU_PHASE_FRAC_BITWIDTH; if (out_h) do_div(temp, out_h); else temp = 0; yvstep = temp; write_wvalue(VS_Y_VSTEP, yvstep << 1); yhcoef_offset = g2d_vsu_calc_fir_coef(yhstep); for (i = 0; i < VSU_PHASE_NUM; i++) { write_wvalue(VS_Y_HCOEF0 + (i << 2), lan2coefftab32_full[yhcoef_offset + i]); } yvcoef_offset = g2d_vsu_calc_fir_coef(yvstep); switch (fmt) { case G2D_FORMAT_IYUV422_V0Y1U0Y0: case G2D_FORMAT_IYUV422_Y1V0Y0U0: case G2D_FORMAT_IYUV422_U0Y1V0Y0: case G2D_FORMAT_IYUV422_Y1U0Y0V0:{ incw = (in_w + 1) >> 1; inch = in_h; format = VSU_FORMAT_YUV422; write_wvalue(VS_C_SIZE, ((inch - 1) << 16) | (incw - 1)); /* chstep = yhstep>>1 cvstep = yvstep */ write_wvalue(VS_C_HSTEP, yhstep); write_wvalue(VS_C_VSTEP, yvstep << 1); chcoef_offset = g2d_vsu_calc_fir_coef(yhstep >> 1); for (i = 0; i < VSU_PHASE_NUM; i++) write_wvalue(VS_C_HCOEF0 + (i << 2), lan2coefftab32_full[chcoef_offset + i]); for (i = 0; i < VSU_PHASE_NUM; i++) write_wvalue(VS_Y_VCOEF0 + (i << 2), linearcoefftab32[i]); break; } case G2D_FORMAT_YUV422UVC_V1U1V0U0: case G2D_FORMAT_YUV422UVC_U1V1U0V0: case G2D_FORMAT_YUV422_PLANAR:{ incw = (in_w + 1) >> 1; inch = in_h; format = VSU_FORMAT_YUV420; write_wvalue(VS_C_SIZE, ((inch - 1) << 16) | (incw - 1)); /* chstep = yhstep>>1 cvstep = yvstep>>1 */ write_wvalue(VS_C_HSTEP, yhstep); write_wvalue(VS_C_VSTEP, yvstep << 1); chcoef_offset = g2d_vsu_calc_fir_coef(yhstep >> 1); for (i = 0; i < VSU_PHASE_NUM; i++) write_wvalue(VS_C_HCOEF0 + (i << 2), lan2coefftab32_full[chcoef_offset + i]); for (i = 0; i < VSU_PHASE_NUM; i++) write_wvalue(VS_Y_VCOEF0 + (i << 2), lan2coefftab32_full[yvcoef_offset + i]); break; } case G2D_FORMAT_YUV420_PLANAR: case G2D_FORMAT_YUV420UVC_V1U1V0U0: case G2D_FORMAT_YUV420UVC_U1V1U0V0:{ incw = (in_w + 1) >> 1; inch = (in_h + 1) >> 1; format = VSU_FORMAT_YUV420; write_wvalue(VS_C_SIZE, ((inch - 1) << 16) | (incw - 1)); write_wvalue(VS_C_HSTEP, yhstep); write_wvalue(VS_C_VSTEP, yvstep); chcoef_offset = g2d_vsu_calc_fir_coef(yhstep >> 1); for (i = 0; i < VSU_PHASE_NUM; i++) write_wvalue(VS_C_HCOEF0 + (i << 2), lan2coefftab32_full[chcoef_offset + i]); for (i = 0; i < VSU_PHASE_NUM; i++) write_wvalue(VS_Y_VCOEF0 + (i << 2), lan2coefftab32_full[yvcoef_offset + i]); break; } case G2D_FORMAT_YUV411_PLANAR: case G2D_FORMAT_YUV411UVC_V1U1V0U0: case G2D_FORMAT_YUV411UVC_U1V1U0V0:{ incw = (in_w + 3) >> 2; inch = in_h; format = VSU_FORMAT_YUV411; write_wvalue(VS_C_SIZE, ((inch - 1) << 16) | (incw - 1)); /* chstep = yhstep>>2 cvstep = yvstep */ write_wvalue(VS_C_HSTEP, yhstep >> 1); write_wvalue(VS_C_VSTEP, yvstep << 1); chcoef_offset = g2d_vsu_calc_fir_coef(yhstep >> 2); for (i = 0; i < VSU_PHASE_NUM; i++) write_wvalue(VS_C_HCOEF0 + (i << 2), lan2coefftab32_full[chcoef_offset + i]); for (i = 0; i < VSU_PHASE_NUM; i++) write_wvalue(VS_Y_VCOEF0 + (i << 2), lan2coefftab32_full[yvcoef_offset + i]); break; } default: format = VSU_FORMAT_RGB; incw = in_w; inch = in_h; write_wvalue(VS_C_SIZE, ((inch - 1) << 16) | (incw - 1)); /* chstep = yhstep cvstep = yvstep */ write_wvalue(VS_C_HSTEP, yhstep << 1); write_wvalue(VS_C_VSTEP, yvstep << 1); chcoef_offset = g2d_vsu_calc_fir_coef(yhstep); for (i = 0; i < VSU_PHASE_NUM; i++) write_wvalue(VS_C_HCOEF0 + (i << 2), lan2coefftab32_full[chcoef_offset + i]); for (i = 0; i < VSU_PHASE_NUM; i++) write_wvalue(VS_Y_VCOEF0 + (i << 2), linearcoefftab32[i]); break; } if (fmt == VSU_FORMAT_YUV420) { /** * yhphase = 0; * yvphase = 0; * chphase = 0xFFFE0000; * cvphase = 0xFFFE0000; */ write_wvalue(VS_Y_HPHASE, 0); write_wvalue(VS_Y_VPHASE0, 0); write_wvalue(VS_C_HPHASE, 0xFFFE0000); write_wvalue(VS_C_VPHASE0, 0xFFFE0000); } else { write_wvalue(VS_Y_HPHASE, 0); write_wvalue(VS_Y_VPHASE0, 0); write_wvalue(VS_C_HPHASE, 0); write_wvalue(VS_C_VPHASE0, 0); } if (fmt >= G2D_FORMAT_IYUV422_Y1U0Y0V0) write_wvalue(VS_CTRL, 0x10001); else write_wvalue(VS_CTRL, 0x00001); return 0; } __s32 g2d_calc_coarse(__u32 format, __u32 inw, __u32 inh, __u32 outw, __u32 outh, __u32 *midw, __u32 *midh) { __u32 tmp; switch (format) { case G2D_FORMAT_IYUV422_V0Y1U0Y0: case G2D_FORMAT_IYUV422_Y1V0Y0U0: case G2D_FORMAT_IYUV422_U0Y1V0Y0: case G2D_FORMAT_IYUV422_Y1U0Y0V0:{ /* interleaved YUV422 format */ *midw = inw; *midh = inh; break; } case G2D_FORMAT_YUV422UVC_V1U1V0U0: case G2D_FORMAT_YUV422UVC_U1V1U0V0: case G2D_FORMAT_YUV422_PLANAR:{ if (inw >= (outw << 3)) { *midw = outw << 3; tmp = (*midw << 16) | inw; write_wvalue(V0_HDS_CTL0, tmp); tmp = (*midw << 15) | ((inw + 1) >> 1); write_wvalue(V0_HDS_CTL1, tmp); } else *midw = inw; if (inh >= (outh << 2)) { *midh = (outh << 2); tmp = (*midh << 16) | inh; write_wvalue(V0_VDS_CTL0, tmp); write_wvalue(V0_VDS_CTL1, tmp); } else *midh = inh; break; } case G2D_FORMAT_YUV420_PLANAR: case G2D_FORMAT_YUV420UVC_V1U1V0U0: case G2D_FORMAT_YUV420UVC_U1V1U0V0:{ if (inw >= (outw << 3)) { *midw = outw << 3; tmp = (*midw << 16) | inw; write_wvalue(V0_HDS_CTL0, tmp); tmp = (*midw << 15) | ((inw + 1) >> 1); write_wvalue(V0_HDS_CTL0, tmp); } else *midw = inw; if (inh >= (outh << 2)) { *midh = (outh << 2); tmp = (*midh << 16) | inh; write_wvalue(V0_VDS_CTL0, tmp); tmp = (*midh << 15) | ((inh + 1) >> 1); write_wvalue(V0_VDS_CTL1, tmp); } else *midh = inh; break; } case G2D_FORMAT_YUV411_PLANAR: case G2D_FORMAT_YUV411UVC_V1U1V0U0: case G2D_FORMAT_YUV411UVC_U1V1U0V0:{ if (inw >= (outw << 3)) { *midw = outw << 3; tmp = ((*midw) << 16) | inw; write_wvalue(V0_HDS_CTL0, tmp); tmp = ((*midw) << 14) | ((inw + 3) >> 2); write_wvalue(V0_HDS_CTL1, tmp); } else *midw = inw; if (inh >= (outh << 2)) { *midh = (outh << 2); tmp = ((*midh) << 16) | inh; write_wvalue(V0_VDS_CTL0, tmp); write_wvalue(V0_VDS_CTL1, tmp); } else *midh = inh; break; } default: if (inw >= (outw << 3)) { *midw = outw << 3; tmp = ((*midw) << 16) | inw; write_wvalue(V0_HDS_CTL0, tmp); write_wvalue(V0_HDS_CTL1, tmp); } else *midw = inw; if (inh >= (outh << 2)) { *midh = (outh << 2); tmp = ((*midh) << 16) | inh; write_wvalue(V0_VDS_CTL0, tmp); write_wvalue(V0_VDS_CTL1, tmp); } else *midh = inh; break; } return 0; } /* * sel: 0-->pipe0 1-->pipe1 other:error */ __s32 g2d_bldin_set(__u32 sel, g2d_rect rect, int premul) { __u32 tmp; __u32 offset; if (sel == 0) { offset = 0; tmp = read_wvalue(BLD_EN_CTL); tmp |= 0x1 << 8; write_wvalue(BLD_EN_CTL, tmp); if (premul) { tmp = read_wvalue(BLD_PREMUL_CTL); tmp |= 0x1; write_wvalue(BLD_PREMUL_CTL, tmp); } } else if (sel == 1) { offset = 0x4; tmp = read_wvalue(BLD_EN_CTL); tmp |= 0x1 << 9; write_wvalue(BLD_EN_CTL, tmp); if (premul) { tmp = read_wvalue(BLD_PREMUL_CTL); tmp |= 0x1 << 1; write_wvalue(BLD_PREMUL_CTL, tmp); } } else return -1; tmp = ((rect.h - 1) << 16) | (rect.w - 1); G2D_INFO_MSG("BLD_CH_ISIZE W: 0x%x\n", rect.w); G2D_INFO_MSG("BLD_CH_ISIZE H: 0x%x\n", rect.h); write_wvalue(BLD_CH_ISIZE0 + offset, tmp); tmp = ((rect.y <= 0 ? 0 : rect.y - 1) << 16) | (rect.x <= 0 ? 0 : rect.x - 1); G2D_INFO_MSG("BLD_CH_ISIZE X: 0x%x\n", rect.x); G2D_INFO_MSG("BLD_CH_ISIZE Y: 0x%x\n", rect.y); write_wvalue(BLD_CH_OFFSET0 + offset, tmp); return 0; } /** * set the bld color space based on the format * if the format is UI, then set the bld in RGB color space * if the format is Video, then set the bld in YUV color space */ __s32 g2d_bld_cs_set(__u32 format) { __u32 tmp; if (format <= G2D_FORMAT_BGRA1010102) { tmp = read_wvalue(BLD_OUT_COLOR); tmp &= 0xFFFFFFFD; write_wvalue(BLD_OUT_COLOR, tmp); } else if (format <= G2D_FORMAT_YUV411_PLANAR) { tmp = read_wvalue(BLD_OUT_COLOR); tmp |= 0x1 << 1; write_wvalue(BLD_OUT_COLOR, tmp); } else return -1; return 0; } __s32 mixer_fillrectangle(g2d_fillrect *para) { g2d_image_enh src_tmp, dst_tmp; g2d_image_enh *src = &src_tmp; g2d_image_enh *dst = &dst_tmp; __s32 result; g2d_mixer_reset(); if (para->flag == G2D_FIL_NONE) { pr_info("fc only!\n"); dst->bbuff = 1; dst->color = para->color; dst->format = g2d_format_trans(para->dst_image.format, para->dst_image.pixel_seq); dst->laddr[0] = para->dst_image.addr[0]; dst->laddr[1] = para->dst_image.addr[1]; dst->laddr[2] = para->dst_image.addr[2]; dst->width = para->dst_image.w; dst->height = para->dst_image.h; dst->clip_rect.x = para->dst_rect.x; dst->clip_rect.y = para->dst_rect.y; dst->clip_rect.w = para->dst_rect.w; dst->clip_rect.h = para->dst_rect.h; dst->gamut = G2D_BT709; dst->alpha = para->alpha; dst->mode = 0; result = g2d_fillrectangle(dst, dst->color); return result; } dst->bbuff = 1; dst->color = para->color; dst->format = g2d_format_trans(para->dst_image.format, para->dst_image.pixel_seq); dst->laddr[0] = para->dst_image.addr[0]; dst->laddr[1] = para->dst_image.addr[1]; dst->laddr[2] = para->dst_image.addr[2]; dst->width = para->dst_image.w; dst->height = para->dst_image.h; dst->clip_rect.x = para->dst_rect.x; dst->clip_rect.y = para->dst_rect.y; dst->clip_rect.w = para->dst_rect.w; dst->clip_rect.h = para->dst_rect.h; dst->gamut = G2D_BT709; dst->alpha = para->alpha; if (para->flag & G2D_FIL_PIXEL_ALPHA) dst->mode = G2D_PIXEL_ALPHA; if (para->flag & G2D_FIL_PLANE_ALPHA) dst->mode = G2D_GLOBAL_ALPHA; if (para->flag & G2D_FIL_MULTI_ALPHA) dst->mode = G2D_MIXER_ALPHA; src->bbuff = 0; src->color = para->color; src->format = dst->format; src->gamut = G2D_BT709; src->format = 0; dst->laddr[0] = para->dst_image.addr[0]; src->width = para->dst_image.w; src->height = para->dst_image.h; src->clip_rect.x = para->dst_rect.x; src->clip_rect.y = para->dst_rect.y; src->clip_rect.w = para->dst_rect.w; src->clip_rect.h = para->dst_rect.h; result = g2d_bsp_bld(src, dst, G2D_BLD_DSTOVER, NULL); return result; } __s32 g2d_fillrectangle(g2d_image_enh *dst, __u32 color_value) { g2d_rect rect0; __u32 tmp; __s32 result; g2d_bsp_reset(); /* set the input layer */ g2d_vlayer_set(0, dst); /* set the fill color value */ g2d_fc_set(0, color_value); if (dst->format >= G2D_FORMAT_IYUV422_V0Y1U0Y0) { g2d_vsu_para_set(dst->format, dst->clip_rect.w, dst->clip_rect.h, dst->clip_rect.w, dst->clip_rect.h, 0xff); g2d_csc_reg_set(1, G2D_RGB2YUV_709); } /* for interleaved test */ if ((dst->format >= G2D_FORMAT_IYUV422_V0Y1U0Y0) && (dst->format <= G2D_FORMAT_IYUV422_Y1U0Y0V0)) { g2d_csc_reg_set(0, G2D_RGB2YUV_709); g2d_csc_reg_set(2, G2D_RGB2YUV_709); write_wvalue(BLD_CSC_CTL, 0x2); g2d_bk_set(0xff123456); porter_duff(G2D_BLD_SRCOVER); write_wvalue(BLD_FILLC0, 0x00108080); write_wvalue(BLD_FILLC1, 0x00108080); write_wvalue(UI0_FILLC, 0xffffffff); write_wvalue(UI1_FILLC, 0xffffffff); } rect0.x = 0; rect0.y = 0; rect0.w = dst->clip_rect.w; rect0.h = dst->clip_rect.h; g2d_bldin_set(0, rect0, dst->bpremul); g2d_bld_cs_set(dst->format); /* ROP sel ch0 pass */ write_wvalue(ROP_CTL, 0xf0); g2d_wb_set(dst); /* start the module */ mixer_irq_enable(); tmp = read_wvalue(G2D_MIXER_CTL); tmp |= 0x80000000; G2D_INFO_MSG("INIT_MODULE: 0x%x\n", tmp); write_wvalue(G2D_MIXER_CTL, tmp); result = g2d_wait_cmd_finish(); return result; } /** * src:source * ptn:pattern * dst:destination * mask:mask * if mask is set to NULL, do ROP3 among src, ptn, and dst using the * fore_flag */ __s32 g2d_bsp_maskblt(g2d_image_enh *src, g2d_image_enh *ptn, g2d_image_enh *mask, g2d_image_enh *dst, __u32 back_flag, __u32 fore_flag) { __u32 tmp; g2d_rect rect0; bool b_pre; __s32 result; /* int b_pre; */ g2d_bsp_reset(); if (dst == NULL) return -1; if (dst->format > G2D_FORMAT_BGRA1010102) return -2; g2d_vlayer_set(0, dst); if (src != NULL) { src->clip_rect.w = dst->clip_rect.w; src->clip_rect.h = dst->clip_rect.h; g2d_uilayer_set(0, src); } if (ptn != NULL) { ptn->clip_rect.w = dst->clip_rect.w; ptn->clip_rect.h = dst->clip_rect.h; g2d_uilayer_set(1, ptn); } if (mask != NULL) { mask->clip_rect.w = dst->clip_rect.w; mask->clip_rect.h = dst->clip_rect.h; g2d_uilayer_set(2, mask); /* set the ROP4 */ write_wvalue(ROP_CTL, 0x1); g2d_rop3_set(0, back_flag & 0xff); g2d_rop3_set(1, fore_flag & 0xff); } else { write_wvalue(ROP_CTL, 0x0); g2d_rop3_set(0, back_flag); } b_pre = dst->bpremul; if (src) b_pre |= src->bpremul; if (ptn) b_pre |= ptn->bpremul; if (b_pre) { /* some layer is not premul */ if (!src->bpremul) { tmp = read_wvalue(UI0_ATTR); tmp |= 0x1 << 16; write_wvalue(UI0_ATTR, tmp); } if (!dst->bpremul) { tmp = read_wvalue(V0_ATTCTL); tmp |= 0x1 << 16; write_wvalue(V0_ATTCTL, tmp); } if (!ptn->bpremul) { tmp = read_wvalue(UI1_ATTR); tmp |= 0x1 << 16; write_wvalue(UI1_ATTR, tmp); } /* set bld in premul data */ write_wvalue(BLD_PREMUL_CTL, 0x1); } /*set bld para */ rect0.x = 0; rect0.y = 0; rect0.w = dst->clip_rect.w; rect0.h = dst->clip_rect.h; g2d_bldin_set(0, rect0, dst->bpremul); g2d_wb_set(dst); /* start the module */ mixer_irq_enable(); tmp = read_wvalue(G2D_MIXER_CTL); tmp |= 0x80000000; G2D_INFO_MSG("INIT_MODULE: 0x%x\n", tmp); write_wvalue(G2D_MIXER_CTL, tmp); result = g2d_wait_cmd_finish(); return result; } __s32 g2d_format_trans(__s32 data_fmt, __s32 pixel_seq) { /* transform the g2d format 2 enhance format */ switch (data_fmt) { case G2D_FMT_ARGB_AYUV8888: return G2D_FORMAT_ARGB8888; case G2D_FMT_BGRA_VUYA8888: return G2D_FORMAT_BGRA8888; case G2D_FMT_ABGR_AVUY8888: return G2D_FORMAT_ABGR8888; case G2D_FMT_RGBA_YUVA8888: return G2D_FORMAT_RGBA8888; case G2D_FMT_XRGB8888: return G2D_FORMAT_XRGB8888; case G2D_FMT_BGRX8888: return G2D_FORMAT_BGRX8888; case G2D_FMT_XBGR8888: return G2D_FORMAT_XBGR8888; case G2D_FMT_RGBX8888: return G2D_FORMAT_RGBX8888; case G2D_FMT_ARGB4444: return G2D_FORMAT_ARGB4444; case G2D_FMT_ABGR4444: return G2D_FORMAT_ABGR4444; case G2D_FMT_RGBA4444: return G2D_FORMAT_RGBA4444; case G2D_FMT_BGRA4444: return G2D_FORMAT_BGRA4444; case G2D_FMT_ARGB1555: return G2D_FORMAT_ARGB1555; case G2D_FMT_ABGR1555: return G2D_FORMAT_ABGR1555; case G2D_FMT_RGBA5551: return G2D_FORMAT_RGBA5551; case G2D_FMT_BGRA5551: return G2D_FORMAT_BGRA5551; case G2D_FMT_RGB565: return G2D_FORMAT_RGB565; case G2D_FMT_BGR565: return G2D_FORMAT_BGR565; case G2D_FMT_IYUV422: if (pixel_seq == G2D_SEQ_VYUY) return G2D_FORMAT_IYUV422_V0Y1U0Y0; if (pixel_seq == G2D_SEQ_YVYU) return G2D_FORMAT_IYUV422_Y1V0Y0U0; return -1; case G2D_FMT_PYUV422UVC: if (pixel_seq == G2D_SEQ_VUVU) return G2D_FORMAT_YUV422UVC_V1U1V0U0; return G2D_FORMAT_YUV422UVC_U1V1U0V0; case G2D_FMT_PYUV420UVC: if (pixel_seq == G2D_SEQ_VUVU) return G2D_FORMAT_YUV420UVC_V1U1V0U0; return G2D_FORMAT_YUV420UVC_U1V1U0V0; case G2D_FMT_PYUV411UVC: if (pixel_seq == G2D_SEQ_VUVU) return G2D_FORMAT_YUV411UVC_V1U1V0U0; return G2D_FORMAT_YUV411UVC_U1V1U0V0; case G2D_FMT_PYUV422: return G2D_FORMAT_YUV422_PLANAR; case G2D_FMT_PYUV420: return G2D_FORMAT_YUV420_PLANAR; case G2D_FMT_PYUV411: return G2D_FORMAT_YUV411_PLANAR; default: return -1; } } __s32 mixer_stretchblt(g2d_stretchblt *para, enum g2d_scan_order scan_order) { g2d_image_enh src_tmp, dst_tmp, tmp_tmp; g2d_image_enh *src = &src_tmp, *dst = &dst_tmp; g2d_image_enh *tmp_img = &tmp_tmp; g2d_ck ck_para_tmp; g2d_ck *ck_para = &ck_para_tmp; __s32 ycnt, ucnt, vcnt; __s32 result; g2d_mixer_reset(); memset(src, 0, sizeof(g2d_image_enh)); memset(dst, 0, sizeof(g2d_image_enh)); memset(tmp_img, 0, sizeof(g2d_image_enh)); memset(ck_para, 0, sizeof(g2d_ck)); src->bbuff = 1; src->color = para->color; src->format = g2d_format_trans(para->src_image.format, para->src_image.pixel_seq); src->laddr[0] = para->src_image.addr[0]; src->laddr[1] = para->src_image.addr[1]; src->laddr[2] = para->src_image.addr[2]; src->width = para->src_image.w; src->height = para->src_image.h; src->clip_rect.x = para->src_rect.x; src->clip_rect.y = para->src_rect.y; src->clip_rect.w = para->src_rect.w; src->clip_rect.h = para->src_rect.h; src->gamut = G2D_BT709; src->alpha = para->alpha; dst->bbuff = 1; dst->color = para->color; dst->format = g2d_format_trans(para->dst_image.format, para->dst_image.pixel_seq); dst->laddr[0] = para->dst_image.addr[0]; dst->laddr[1] = para->dst_image.addr[1]; dst->laddr[2] = para->dst_image.addr[2]; dst->width = para->dst_image.w; dst->height = para->dst_image.h; dst->clip_rect.x = para->dst_rect.x; dst->clip_rect.y = para->dst_rect.y; dst->clip_rect.w = para->dst_rect.w; dst->clip_rect.h = para->dst_rect.h; dst->gamut = G2D_BT709; dst->alpha = para->alpha; if (para->flag == G2D_BLT_NONE) { /* not ROT case */ dst->format = g2d_format_trans(para->dst_image.format, para->dst_image.pixel_seq); if (scan_order == G2D_SM_DTLR) result = g2d_bsp_bitblt(src, dst, G2D_BLT_NONE | G2D_SM_DTLR_1); else result = g2d_bsp_bitblt(src, dst, G2D_BLT_NONE); return result; } else { tmp_img->bbuff = 1; tmp_img->color = para->color; tmp_img->format = g2d_format_trans(para->src_image.format, para->src_image.pixel_seq); g2d_byte_cal(src->format, &ycnt, &ucnt, &vcnt); tmp_img->laddr[0] = para->src_image.addr[0] + src->width * src->height * ycnt; tmp_img->laddr[1] = para->src_image.addr[1]; tmp_img->laddr[2] = para->src_image.addr[2]; tmp_img->width = para->dst_image.w; tmp_img->height = para->dst_image.h; tmp_img->clip_rect.x = para->dst_rect.x; tmp_img->clip_rect.y = para->dst_rect.x; tmp_img->gamut = G2D_BT709; tmp_img->alpha = para->alpha; if (para->flag & G2D_BLT_SRC_PREMULTIPLY) { src->bpremul = 1; tmp_img->bpremul = 1; dst->bpremul = 1; } if (para->flag & G2D_BLT_PIXEL_ALPHA) { src->mode = G2D_PIXEL_ALPHA; tmp_img->mode = G2D_PIXEL_ALPHA; dst->mode = G2D_PIXEL_ALPHA; } if (para->flag & G2D_BLT_PLANE_ALPHA) { src->mode = G2D_GLOBAL_ALPHA; tmp_img->mode = G2D_GLOBAL_ALPHA; dst->mode = G2D_GLOBAL_ALPHA; } if (para->flag & G2D_BLT_MULTI_ALPHA) { src->mode = G2D_MIXER_ALPHA; tmp_img->mode = G2D_MIXER_ALPHA; dst->mode = G2D_MIXER_ALPHA; } ck_para->match_rule = 0; ck_para->max_color = para->color; ck_para->min_color = para->color; if (para->flag & 0xfe0) { switch (para->flag & 0xfe0) { case G2D_BLT_FLIP_HORIZONTAL: pr_info("HFLIP\n"); g2d_bsp_bitblt(src, tmp_img, G2D_ROT_H); break; case G2D_BLT_FLIP_VERTICAL: pr_info("VFLIP\n"); g2d_bsp_bitblt(src, tmp_img, G2D_ROT_V); break; case G2D_BLT_ROTATE90: pr_info("ROT90\n"); g2d_bsp_bitblt(src, tmp_img, G2D_ROT_90); break; case G2D_BLT_ROTATE180: pr_info("ROT180\n"); g2d_bsp_bitblt(src, tmp_img, G2D_ROT_180); break; case G2D_BLT_ROTATE270: pr_info("ROT270\n"); g2d_bsp_bitblt(src, tmp_img, G2D_ROT_270); break; case G2D_BLT_MIRROR45: pr_info("ROT45\n"); g2d_bsp_bitblt(src, tmp_img, G2D_ROT_90 | G2D_ROT_H); break; case G2D_BLT_MIRROR135: pr_info("ROT135\n"); g2d_bsp_bitblt(src, tmp_img, G2D_ROT_90 | G2D_ROT_V); break; default: return -1; } result = g2d_bsp_bitblt(tmp_img, dst, G2D_BLT_NONE); } else result = g2d_bsp_bitblt(src, dst, G2D_BLT_NONE); return result; } } __s32 mixer_blt(g2d_blt *para, enum g2d_scan_order scan_order) { g2d_image_enh src_tmp, dst_tmp, tmp_tmp; g2d_image_enh *src = &src_tmp; g2d_image_enh *dst = &dst_tmp; g2d_image_enh *tmp_img = &tmp_tmp; g2d_ck ck_para_tmp; g2d_ck *ck_para = &ck_para_tmp; __s32 ycnt, ucnt, vcnt; memset(src, 0, sizeof(g2d_image_enh)); memset(dst, 0, sizeof(g2d_image_enh)); memset(tmp_img, 0, sizeof(g2d_image_enh)); memset(ck_para, 0, sizeof(g2d_ck)); G2D_INFO_MSG("Input_G2D_Format: 0x%x\n", para->src_image.format); G2D_INFO_MSG("BITBLT_flag: 0x%x\n", para->flag); G2D_INFO_MSG("inPICWidth: %d\n", para->src_image.w); G2D_INFO_MSG("inPICHeight: %d\n", para->src_image.h); G2D_INFO_MSG("inRectX: %d\n", para->src_rect.x); G2D_INFO_MSG("inRectY: %d\n", para->src_rect.y); G2D_INFO_MSG("inRectW: %d\n", para->src_rect.w); G2D_INFO_MSG("inRectH: %d\n", para->src_rect.h); G2D_INFO_MSG("Output_G2D_Format: 0x%x\n", para->dst_image.format); G2D_INFO_MSG("outPICWidth: %d\n", para->dst_image.w); G2D_INFO_MSG("outPICHeight: %d\n", para->dst_image.h); G2D_INFO_MSG("outRectX: %d\n", para->dst_x); G2D_INFO_MSG("outRectY: %d\n", para->dst_y); src->bbuff = 1; src->color = para->color; src->format = g2d_format_trans(para->src_image.format, para->src_image.pixel_seq); src->laddr[0] = para->src_image.addr[0]; src->laddr[1] = para->src_image.addr[1]; src->laddr[2] = para->src_image.addr[2]; src->width = para->src_image.w; src->height = para->src_image.h; src->clip_rect.x = para->src_rect.x; src->clip_rect.y = para->src_rect.y; src->clip_rect.w = para->src_rect.w; src->clip_rect.h = para->src_rect.h; src->gamut = G2D_BT709; src->alpha = para->alpha; dst->bbuff = 1; dst->format = g2d_format_trans(para->dst_image.format, para->dst_image.pixel_seq); dst->laddr[0] = para->dst_image.addr[0]; dst->laddr[1] = para->dst_image.addr[1]; dst->laddr[2] = para->dst_image.addr[2]; dst->width = para->dst_image.w; dst->height = para->dst_image.h; dst->clip_rect.x = para->dst_x; dst->clip_rect.y = para->dst_y; dst->clip_rect.w = src->clip_rect.w; dst->clip_rect.h = src->clip_rect.h; dst->gamut = G2D_BT709; dst->alpha = para->alpha; G2D_INFO_MSG("inPICaddr0: 0x%x\n", src->laddr[0]); G2D_INFO_MSG("inPICaddr1: 0x%x\n", src->laddr[1]); G2D_INFO_MSG("inPICaddr2: 0x%x\n", src->laddr[2]); G2D_INFO_MSG("outPICaddr0: 0x%x\n", dst->laddr[0]); G2D_INFO_MSG("outPICaddr1: 0x%x\n", dst->laddr[1]); G2D_INFO_MSG("outPICaddr2: 0x%x\n", dst->laddr[2]); if ((para->flag == G2D_BLT_NONE) || (para->flag == G2D_BLT_FLIP_HORIZONTAL) || (para->flag == G2D_BLT_FLIP_VERTICAL) || (para->flag == G2D_BLT_ROTATE90) || (para->flag == G2D_BLT_ROTATE180) || (para->flag == G2D_BLT_ROTATE270) || (para->flag == G2D_BLT_MIRROR45) || (para->flag == G2D_BLT_MIRROR135)) { /* ROT case */ switch (para->flag) { case G2D_BLT_NONE: if (scan_order == G2D_SM_DTLR) g2d_bsp_bitblt(src, dst, G2D_BLT_NONE | G2D_SM_DTLR_1); else g2d_bsp_bitblt(src, dst, G2D_BLT_NONE); return 0; case G2D_BLT_FLIP_HORIZONTAL: g2d_bsp_bitblt(src, dst, G2D_ROT_H); return 0; case G2D_BLT_FLIP_VERTICAL: g2d_bsp_bitblt(src, dst, G2D_ROT_V); return 0; case G2D_BLT_ROTATE90: g2d_bsp_bitblt(src, dst, G2D_ROT_90); return 0; case G2D_BLT_ROTATE180: g2d_bsp_bitblt(src, dst, G2D_ROT_180); return 0; case G2D_BLT_ROTATE270: g2d_bsp_bitblt(src, dst, G2D_ROT_270); return 0; case G2D_BLT_MIRROR45: g2d_bsp_bitblt(src, dst, G2D_ROT_90 | G2D_ROT_H); return 0; case G2D_BLT_MIRROR135: g2d_bsp_bitblt(src, dst, G2D_ROT_90 | G2D_ROT_V); return 0; default: return -1; } } else { tmp_img->bbuff = 1; tmp_img->format = src->format; tmp_img->color = para->color; tmp_img->format = src->format; g2d_byte_cal(src->format, &ycnt, &ucnt, &vcnt); tmp_img->laddr[0] = para->src_image.addr[0] + src->height * src->width * ycnt; tmp_img->width = para->dst_image.w; tmp_img->height = para->dst_image.h; tmp_img->clip_rect.x = para->dst_x; tmp_img->clip_rect.y = para->dst_y; tmp_img->gamut = G2D_BT709; tmp_img->alpha = para->alpha; G2D_INFO_MSG("tmpPICaddr0: 0x%x\n", tmp_img->laddr[0]); if (para->flag & G2D_BLT_SRC_PREMULTIPLY) dst->bpremul = 1; if (para->flag & G2D_BLT_PIXEL_ALPHA) dst->mode = G2D_PIXEL_ALPHA; if (para->flag & G2D_BLT_PLANE_ALPHA) dst->mode = G2D_GLOBAL_ALPHA; if (para->flag & G2D_BLT_MULTI_ALPHA) dst->mode = G2D_MIXER_ALPHA; if (para->flag & G2D_BLT_SRC_PREMULTIPLY) { src->bpremul = 1; tmp_img->bpremul = 1; } if (para->flag & G2D_BLT_PIXEL_ALPHA) { src->mode = G2D_PIXEL_ALPHA; tmp_img->mode = G2D_PIXEL_ALPHA; } if (para->flag & G2D_BLT_PLANE_ALPHA) { src->mode = G2D_GLOBAL_ALPHA; tmp_img->mode = G2D_GLOBAL_ALPHA; } if (para->flag & G2D_BLT_MULTI_ALPHA) { src->mode = G2D_MIXER_ALPHA; tmp_img->mode = G2D_MIXER_ALPHA; } ck_para->match_rule = 0; ck_para->max_color = para->color; ck_para->min_color = para->color; if (para->flag & 0xfe0) { switch (para->flag & 0xfe0) { case G2D_BLT_FLIP_HORIZONTAL: pr_info("HFLIP\n"); g2d_bsp_bitblt(src, tmp_img, G2D_ROT_H); break; case G2D_BLT_FLIP_VERTICAL: pr_info("VFLIP\n"); g2d_bsp_bitblt(src, tmp_img, G2D_ROT_V); break; case G2D_BLT_ROTATE90: pr_info("ROT90\n"); g2d_bsp_bitblt(src, tmp_img, G2D_ROT_90); break; case G2D_BLT_ROTATE180: pr_info("ROT180\n"); g2d_bsp_bitblt(src, tmp_img, G2D_ROT_180); break; case G2D_BLT_ROTATE270: pr_info("ROT270\n"); g2d_bsp_bitblt(src, tmp_img, G2D_ROT_270); break; case G2D_BLT_MIRROR45: pr_info("ROT45\n"); g2d_bsp_bitblt(src, tmp_img, G2D_ROT_90 | G2D_ROT_H); break; case G2D_BLT_MIRROR135: pr_info("ROT135\n"); g2d_bsp_bitblt(src, tmp_img, G2D_ROT_90 | G2D_ROT_V); break; default: return -1; } G2D_INFO_MSG("tmpRectX: %d\n", tmp_img->clip_rect.x); G2D_INFO_MSG("tmpRectY: %d\n", tmp_img->clip_rect.y); G2D_INFO_MSG("tmpRectW: %d\n", tmp_img->clip_rect.w); G2D_INFO_MSG("tmpRectH: %d\n", tmp_img->clip_rect.h); pr_info("begin BLD OPER!\n"); dst->clip_rect.w = tmp_img->clip_rect.w; dst->clip_rect.h = tmp_img->clip_rect.h; /*g2d_bsp_bitblt(tmp_img, dst, G2D_BLT_NONE); */ g2d_bsp_bld(tmp_img, dst, G2D_BLD_DSTOVER, NULL); } else { /*g2d_bsp_bitblt(tmp_img, dst, G2D_BLT_NONE); */ g2d_bsp_bld(src, dst, G2D_BLD_DSTOVER, NULL); } return 0; } } __s32 g2d_bsp_bitblt(g2d_image_enh *src, g2d_image_enh *dst, __u32 flag) { g2d_rect rect0, rect1; bool bpre; __u32 ycnt, ucnt, vcnt; __u32 pitch0, pitch1, pitch2; __u64 addr0, addr1, addr2; __u32 midw, midh; __u32 tmp; __s32 result; g2d_bsp_reset(); if (dst == NULL) return -1; if (src == NULL) return -2; G2D_INFO_MSG("BITBLT_flag: 0x%x\n", flag); if (G2D_BLT_NONE == (flag & 0x0fffffff)) { G2D_INFO_MSG("Input info:---------------------------------\n"); G2D_INFO_MSG("Src_fd: %d\n", src->fd); G2D_INFO_MSG("Format: 0x%x\n", src->format); G2D_INFO_MSG("BITBLT_alpha_mode: 0x%x\n", src->mode); G2D_INFO_MSG("BITBLT_alpha_val: 0x%x\n", src->alpha); G2D_INFO_MSG("inClipRectX: %d\n", src->clip_rect.x); G2D_INFO_MSG("inClipRectY: %d\n", src->clip_rect.y); G2D_INFO_MSG("inClipRectW: %d\n", src->clip_rect.w); G2D_INFO_MSG("inClipRectH: %d\n", src->clip_rect.h); G2D_INFO_MSG("Output info:--------------------------------\n"); G2D_INFO_MSG("Dst_fd: %d\n", dst->fd); G2D_INFO_MSG("Format: 0x%x\n", dst->format); G2D_INFO_MSG("outClipRectX: %d\n", dst->clip_rect.x); G2D_INFO_MSG("outClipRectY: %d\n", dst->clip_rect.y); G2D_INFO_MSG("outClipRectW: %d\n", dst->clip_rect.w); G2D_INFO_MSG("outClipRectH: %d\n", dst->clip_rect.h); /*single src opt */ g2d_vlayer_set(0, src); if (src->mode) { /* need abp process */ g2d_uilayer_set(2, dst); } if ((src->format >= G2D_FORMAT_IYUV422_V0Y1U0Y0) || (src->clip_rect.w != dst->clip_rect.w) || (src->clip_rect.h != dst->clip_rect.h)) { g2d_calc_coarse(src->format, src->clip_rect.w, src->clip_rect.h, dst->clip_rect.w, dst->clip_rect.h, &midw, &midh); g2d_vsu_para_set(src->format, midw, midh, dst->clip_rect.w, dst->clip_rect.h, 0xff); } write_wvalue(ROP_CTL, 0xf0); /*set bld para */ rect0.x = 0; rect0.y = 0; rect0.w = dst->clip_rect.w; rect0.h = dst->clip_rect.h; g2d_bldin_set(0, rect0, dst->bpremul); g2d_bld_cs_set(src->format); if (src->mode) { /* need abp process */ rect1.x = 0; rect1.y = 0; rect1.w = dst->clip_rect.w; rect1.h = dst->clip_rect.h; g2d_bldin_set(1, rect1, dst->bpremul); } if ((src->format <= G2D_FORMAT_BGRA1010102) && (dst->format > G2D_FORMAT_BGRA1010102)) { g2d_csc_reg_set(2, G2D_RGB2YUV_709); } if ((src->format > G2D_FORMAT_BGRA1010102) && (dst->format <= G2D_FORMAT_BGRA1010102)) { g2d_csc_reg_set(2, G2D_YUV2RGB_709); } g2d_wb_set(dst); } else if (flag & 0xff) { /* ROP2 operate */ if ((src->format > G2D_FORMAT_BGRA1010102) | (dst->format > G2D_FORMAT_BGRA1010102)) return -3; g2d_uilayer_set(0, dst); g2d_vlayer_set(0, src); /* bpre = 0; */ bpre = false; if (src->bpremul || dst->bpremul) { bpre = true; /* bpre = 1; */ /* some layer is premul */ if (!src->bpremul) { tmp = read_wvalue(V0_ATTCTL); tmp |= 0x1 << 16; write_wvalue(V0_ATTCTL, tmp); } if (!dst->bpremul) { tmp = read_wvalue(UI0_ATTR); tmp |= 0x1 << 16; write_wvalue(UI0_ATTR, tmp); } } if ((src->clip_rect.w != dst->clip_rect.w) || (src->clip_rect.h != dst->clip_rect.h)) { g2d_calc_coarse(src->format, src->clip_rect.w, src->clip_rect.h, dst->clip_rect.w, dst->clip_rect.h, &midw, &midh); g2d_vsu_para_set(src->format, midw, midh, dst->clip_rect.w, dst->clip_rect.h, 0xff); } write_wvalue(ROP_CTL, 0x0); g2d_rop2_set(flag & 0xff); tmp = read_wvalue(ROP_INDEX0); tmp |= 0x2; write_wvalue(ROP_INDEX0, tmp); /*set bld para */ rect0.x = 0; rect0.y = 0; rect0.w = dst->clip_rect.w; rect0.h = dst->clip_rect.h; g2d_bldin_set(0, rect0, bpre); g2d_wb_set(dst); } else if (flag & 0xff00) { /* ROT operate */ tmp = 1; if (flag & G2D_ROT_H) tmp |= 0x1 << 7; if (flag & G2D_ROT_V) tmp |= 0x1 << 6; if ((flag & 0xf00) == G2D_ROT_90) tmp |= 0x1 << 4; if ((flag & 0xf00) == G2D_ROT_180) tmp |= 0x2 << 4; if ((flag & 0xf00) == G2D_ROT_270) tmp |= 0x3 << 4; if ((flag & 0xf00) == G2D_ROT_0) tmp |= 0x0 << 4; G2D_INFO_MSG("ROT input info: ----------------------------\n"); G2D_INFO_MSG("Src_fd: %d\n", src->fd); G2D_INFO_MSG("Format: 0x%x\n", src->format); G2D_INFO_MSG("Flag: 0x%x\n", flag); G2D_INFO_MSG("inClipRectX: %d\n", src->clip_rect.x); G2D_INFO_MSG("inClipRectY: %d\n", src->clip_rect.y); G2D_INFO_MSG("inClipRectW: %d\n", src->clip_rect.w); G2D_INFO_MSG("inClipRectH: %d\n", src->clip_rect.h); write_wvalue(ROT_CTL, tmp); write_wvalue(ROT_IFMT, src->format & 0x3F); write_wvalue(ROT_ISIZE, ((((src->clip_rect.h - 1) & 0x1fff) << 16)) | ((src->clip_rect.w - 1) & 0x1fff)); G2D_INFO_MSG("ROT_IFMT: 0x%x\n", read_wvalue(ROT_IFMT)); G2D_INFO_MSG("ROT_ISIZE: 0x%x\n", read_wvalue(ROT_ISIZE)); G2D_INFO_MSG("SRC_align: %d, %d, %d\n", src->align[0], src->align[1], src->align[2]); G2D_INFO_MSG("DST_align: %d, %d, %d\n", dst->align[0], dst->align[1], dst->align[2]); g2d_byte_cal(src->format, &ycnt, &ucnt, &vcnt); pitch0 = cal_align(ycnt * src->width, src->align[0]); write_wvalue(ROT_IPITCH0, pitch0); pitch1 = cal_align(ucnt * (src->width >> 1), src->align[1]); write_wvalue(ROT_IPITCH1, pitch1); pitch2 = cal_align(vcnt * (src->width >> 1), src->align[2]); write_wvalue(ROT_IPITCH2, pitch2); G2D_INFO_MSG("ROT_InPITCH: %d, %d, %d\n", pitch0, pitch1, pitch2); addr0 = src->laddr[0] + ((__u64) src->haddr[0] << 32) + pitch0 * src->clip_rect.y + ycnt * src->clip_rect.x; write_wvalue(ROT_ILADD0, addr0 & 0xffffffff); write_wvalue(ROT_IHADD0, (addr0 >> 32) & 0xff); addr1 = src->laddr[1] + ((__u64) src->haddr[1] << 32) + pitch1 * src->clip_rect.y + ucnt * src->clip_rect.x; write_wvalue(ROT_ILADD1, addr1 & 0xffffffff); write_wvalue(ROT_IHADD1, (addr1 >> 32) & 0xff); addr2 = src->laddr[2] + ((__u64) src->haddr[2] << 32) + pitch2 * src->clip_rect.y + vcnt * src->clip_rect.x; write_wvalue(ROT_ILADD2, addr2 & 0xffffffff); write_wvalue(ROT_IHADD2, (addr2 >> 32) & 0xff); if (((flag & 0xf00) == G2D_ROT_90) | ((flag & 0xf00) == G2D_ROT_270)) { dst->clip_rect.w = src->clip_rect.h; dst->clip_rect.h = src->clip_rect.w; } else { dst->clip_rect.w = src->clip_rect.w; dst->clip_rect.h = src->clip_rect.h; } write_wvalue(ROT_OSIZE, ((((dst->clip_rect.h - 1) & 0x1fff) << 16)) | ((dst->clip_rect.w - 1) & 0x1fff)); /* YUV output fmt only support 420 */ if (src->format == G2D_FORMAT_YUV422UVC_V1U1V0U0) dst->format = G2D_FORMAT_YUV420UVC_V1U1V0U0; else if (src->format == G2D_FORMAT_YUV422UVC_U1V1U0V0) dst->format = G2D_FORMAT_YUV420UVC_U1V1U0V0; else if (src->format == G2D_FORMAT_YUV422_PLANAR) dst->format = G2D_FORMAT_YUV420_PLANAR; else dst->format = src->format; g2d_byte_cal(dst->format, &ycnt, &ucnt, &vcnt); G2D_INFO_MSG("ROT output info: ----------------------------\n"); G2D_INFO_MSG("Dst_fd: %d\n", dst->fd); G2D_INFO_MSG("Format: 0x%x\n", dst->format); pitch0 = cal_align(ycnt * dst->width, dst->align[0]); write_wvalue(ROT_OPITCH0, pitch0); pitch1 = cal_align(ucnt * (dst->width >> 1), dst->align[1]); write_wvalue(ROT_OPITCH1, pitch1); pitch2 = cal_align(vcnt * (dst->width >> 1), dst->align[2]); write_wvalue(ROT_OPITCH2, pitch2); G2D_INFO_MSG("ROT_OutPITCH: %d, %d, %d\n", pitch0, pitch1, pitch2); G2D_INFO_MSG("outClipRectX: %d\n", dst->clip_rect.x); G2D_INFO_MSG("outClipRectY: %d\n", dst->clip_rect.y); G2D_INFO_MSG("outClipRectW: %d\n", dst->clip_rect.w); G2D_INFO_MSG("outClipRectH: %d\n", dst->clip_rect.h); addr0 = dst->laddr[0] + ((__u64) dst->haddr[0] << 32) + pitch0 * dst->clip_rect.y + ycnt * dst->clip_rect.x; write_wvalue(ROT_OLADD0, addr0 & 0xffffffff); write_wvalue(ROT_OHADD0, (addr0 >> 32) & 0xff); addr1 = dst->laddr[1] + ((__u64) dst->haddr[1] << 32) + pitch1 * dst->clip_rect.y + ucnt * dst->clip_rect.x; write_wvalue(ROT_OLADD1, addr1 & 0xffffffff); write_wvalue(ROT_OHADD1, (addr1 >> 32) & 0xff); addr2 = dst->laddr[2] + ((__u64) dst->haddr[2] << 32) + pitch2 * dst->clip_rect.y + vcnt * dst->clip_rect.x; write_wvalue(ROT_OLADD2, addr2 & 0xffffffff); write_wvalue(ROT_OHADD2, (addr2 >> 32) & 0xff); G2D_INFO_MSG("DST_ADDR0: 0x%x\n", dst->laddr[0]); G2D_INFO_MSG("DST_ADDR1: 0x%x\n", dst->laddr[1]); G2D_INFO_MSG("DST_ADDR2: 0x%x\n", dst->laddr[2]); /* start the module */ rot_irq_enable(); tmp = read_wvalue(ROT_CTL); tmp |= (0x1 << 31); G2D_INFO_MSG("init_module: 0x%x\n", tmp); write_wvalue(ROT_CTL, tmp); result = g2d_wait_cmd_finish(); return result; } g2d_scan_order_fun(flag & 0xf0000000); /* start the module */ mixer_irq_enable(); tmp = read_wvalue(G2D_MIXER_CTL); tmp |= 0x80000000; G2D_INFO_MSG("INIT_MODULE: 0x%x\n", tmp); write_wvalue(G2D_MIXER_CTL, tmp); result = g2d_wait_cmd_finish(); return result; } __s32 g2d_bsp_bld(g2d_image_enh *src, g2d_image_enh *dst, __u32 flag, g2d_ck *ck_para) { g2d_rect rect0, rect1; __u32 tmp; __s32 result; if (dst == NULL) return -1; g2d_mixer_reset(); g2d_vlayer_set(0, dst); g2d_uilayer_set(2, src); if ((dst->format > G2D_FORMAT_BGRA1010102) && (src->format <= G2D_FORMAT_BGRA1010102)) g2d_csc_reg_set(1, G2D_RGB2YUV_709); write_wvalue(ROP_CTL, 0xF0); rect0.x = 0; rect0.y = 0; rect0.w = dst->clip_rect.w; rect0.h = dst->clip_rect.h; rect1.x = 0; rect1.y = 0; rect1.w = src->clip_rect.w; rect1.h = src->clip_rect.h; g2d_bldin_set(0, rect0, dst->bpremul); g2d_bldin_set(1, rect1, src->bpremul); G2D_INFO_MSG("BLD_FLAG: 0x%x\n", flag); porter_duff(flag & 0xFFF); if (flag & G2D_CK_SRC) write_wvalue(BLD_KEY_CTL, 0x3); else if (flag & G2D_CK_DST) write_wvalue(BLD_KEY_CTL, 0x1); if (ck_para != NULL) ck_para_set(ck_para); g2d_wb_set(dst); g2d_bld_cs_set(dst->format); /* start the modult */ mixer_irq_enable(); tmp = read_wvalue(G2D_MIXER_CTL); tmp |= 0x80000000; G2D_INFO_MSG("INIT_MODULE: 0x%x\n", tmp); write_wvalue(G2D_MIXER_CTL, tmp); result = g2d_wait_cmd_finish(); return result; } __s32 g2d_get_clk_cnt(__u32 *clk) { __s32 ret; ret = read_wvalue(G2D_MIXER_CLK); if (ret != 0) return -1; /* clear clk cnt */ write_wvalue(G2D_MIXER_CLK, 0); return 0; } __u32 mixer_set_reg_base(unsigned long addr) { base_addr = addr; return 0; }