18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. 48c2ecf20Sopenharmony_ci * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci#include <linux/via-core.h> 88c2ecf20Sopenharmony_ci#include "global.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci/* 118c2ecf20Sopenharmony_ci * Figure out an appropriate bytes-per-pixel setting. 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_cistatic int viafb_set_bpp(void __iomem *engine, u8 bpp) 148c2ecf20Sopenharmony_ci{ 158c2ecf20Sopenharmony_ci u32 gemode; 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci /* Preserve the reserved bits */ 188c2ecf20Sopenharmony_ci /* Lowest 2 bits to zero gives us no rotation */ 198c2ecf20Sopenharmony_ci gemode = readl(engine + VIA_REG_GEMODE) & 0xfffffcfc; 208c2ecf20Sopenharmony_ci switch (bpp) { 218c2ecf20Sopenharmony_ci case 8: 228c2ecf20Sopenharmony_ci gemode |= VIA_GEM_8bpp; 238c2ecf20Sopenharmony_ci break; 248c2ecf20Sopenharmony_ci case 16: 258c2ecf20Sopenharmony_ci gemode |= VIA_GEM_16bpp; 268c2ecf20Sopenharmony_ci break; 278c2ecf20Sopenharmony_ci case 32: 288c2ecf20Sopenharmony_ci gemode |= VIA_GEM_32bpp; 298c2ecf20Sopenharmony_ci break; 308c2ecf20Sopenharmony_ci default: 318c2ecf20Sopenharmony_ci printk(KERN_WARNING "viafb_set_bpp: Unsupported bpp %d\n", bpp); 328c2ecf20Sopenharmony_ci return -EINVAL; 338c2ecf20Sopenharmony_ci } 348c2ecf20Sopenharmony_ci writel(gemode, engine + VIA_REG_GEMODE); 358c2ecf20Sopenharmony_ci return 0; 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height, 408c2ecf20Sopenharmony_ci u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y, 418c2ecf20Sopenharmony_ci u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y, 428c2ecf20Sopenharmony_ci u32 fg_color, u32 bg_color, u8 fill_rop) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci u32 ge_cmd = 0, tmp, i; 458c2ecf20Sopenharmony_ci int ret; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci if (!op || op > 3) { 488c2ecf20Sopenharmony_ci printk(KERN_WARNING "hw_bitblt_1: Invalid operation: %d\n", op); 498c2ecf20Sopenharmony_ci return -EINVAL; 508c2ecf20Sopenharmony_ci } 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) { 538c2ecf20Sopenharmony_ci if (src_x < dst_x) { 548c2ecf20Sopenharmony_ci ge_cmd |= 0x00008000; 558c2ecf20Sopenharmony_ci src_x += width - 1; 568c2ecf20Sopenharmony_ci dst_x += width - 1; 578c2ecf20Sopenharmony_ci } 588c2ecf20Sopenharmony_ci if (src_y < dst_y) { 598c2ecf20Sopenharmony_ci ge_cmd |= 0x00004000; 608c2ecf20Sopenharmony_ci src_y += height - 1; 618c2ecf20Sopenharmony_ci dst_y += height - 1; 628c2ecf20Sopenharmony_ci } 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci if (op == VIA_BITBLT_FILL) { 668c2ecf20Sopenharmony_ci switch (fill_rop) { 678c2ecf20Sopenharmony_ci case 0x00: /* blackness */ 688c2ecf20Sopenharmony_ci case 0x5A: /* pattern inversion */ 698c2ecf20Sopenharmony_ci case 0xF0: /* pattern copy */ 708c2ecf20Sopenharmony_ci case 0xFF: /* whiteness */ 718c2ecf20Sopenharmony_ci break; 728c2ecf20Sopenharmony_ci default: 738c2ecf20Sopenharmony_ci printk(KERN_WARNING "hw_bitblt_1: Invalid fill rop: " 748c2ecf20Sopenharmony_ci "%u\n", fill_rop); 758c2ecf20Sopenharmony_ci return -EINVAL; 768c2ecf20Sopenharmony_ci } 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci ret = viafb_set_bpp(engine, dst_bpp); 808c2ecf20Sopenharmony_ci if (ret) 818c2ecf20Sopenharmony_ci return ret; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci if (op != VIA_BITBLT_FILL) { 848c2ecf20Sopenharmony_ci if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000) 858c2ecf20Sopenharmony_ci || src_y & 0xFFFFF000) { 868c2ecf20Sopenharmony_ci printk(KERN_WARNING "hw_bitblt_1: Unsupported source " 878c2ecf20Sopenharmony_ci "x/y %d %d\n", src_x, src_y); 888c2ecf20Sopenharmony_ci return -EINVAL; 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci tmp = src_x | (src_y << 16); 918c2ecf20Sopenharmony_ci writel(tmp, engine + 0x08); 928c2ecf20Sopenharmony_ci } 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) { 958c2ecf20Sopenharmony_ci printk(KERN_WARNING "hw_bitblt_1: Unsupported destination x/y " 968c2ecf20Sopenharmony_ci "%d %d\n", dst_x, dst_y); 978c2ecf20Sopenharmony_ci return -EINVAL; 988c2ecf20Sopenharmony_ci } 998c2ecf20Sopenharmony_ci tmp = dst_x | (dst_y << 16); 1008c2ecf20Sopenharmony_ci writel(tmp, engine + 0x0C); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) { 1038c2ecf20Sopenharmony_ci printk(KERN_WARNING "hw_bitblt_1: Unsupported width/height " 1048c2ecf20Sopenharmony_ci "%d %d\n", width, height); 1058c2ecf20Sopenharmony_ci return -EINVAL; 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci tmp = (width - 1) | ((height - 1) << 16); 1088c2ecf20Sopenharmony_ci writel(tmp, engine + 0x10); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci if (op != VIA_BITBLT_COLOR) 1118c2ecf20Sopenharmony_ci writel(fg_color, engine + 0x18); 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci if (op == VIA_BITBLT_MONO) 1148c2ecf20Sopenharmony_ci writel(bg_color, engine + 0x1C); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci if (op != VIA_BITBLT_FILL) { 1178c2ecf20Sopenharmony_ci tmp = src_mem ? 0 : src_addr; 1188c2ecf20Sopenharmony_ci if (dst_addr & 0xE0000007) { 1198c2ecf20Sopenharmony_ci printk(KERN_WARNING "hw_bitblt_1: Unsupported source " 1208c2ecf20Sopenharmony_ci "address %X\n", tmp); 1218c2ecf20Sopenharmony_ci return -EINVAL; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci tmp >>= 3; 1248c2ecf20Sopenharmony_ci writel(tmp, engine + 0x30); 1258c2ecf20Sopenharmony_ci } 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci if (dst_addr & 0xE0000007) { 1288c2ecf20Sopenharmony_ci printk(KERN_WARNING "hw_bitblt_1: Unsupported destination " 1298c2ecf20Sopenharmony_ci "address %X\n", dst_addr); 1308c2ecf20Sopenharmony_ci return -EINVAL; 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci tmp = dst_addr >> 3; 1338c2ecf20Sopenharmony_ci writel(tmp, engine + 0x34); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci if (op == VIA_BITBLT_FILL) 1368c2ecf20Sopenharmony_ci tmp = 0; 1378c2ecf20Sopenharmony_ci else 1388c2ecf20Sopenharmony_ci tmp = src_pitch; 1398c2ecf20Sopenharmony_ci if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) { 1408c2ecf20Sopenharmony_ci printk(KERN_WARNING "hw_bitblt_1: Unsupported pitch %X %X\n", 1418c2ecf20Sopenharmony_ci tmp, dst_pitch); 1428c2ecf20Sopenharmony_ci return -EINVAL; 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci tmp = VIA_PITCH_ENABLE | (tmp >> 3) | (dst_pitch << (16 - 3)); 1458c2ecf20Sopenharmony_ci writel(tmp, engine + 0x38); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci if (op == VIA_BITBLT_FILL) 1488c2ecf20Sopenharmony_ci ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001; 1498c2ecf20Sopenharmony_ci else { 1508c2ecf20Sopenharmony_ci ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */ 1518c2ecf20Sopenharmony_ci if (src_mem) 1528c2ecf20Sopenharmony_ci ge_cmd |= 0x00000040; 1538c2ecf20Sopenharmony_ci if (op == VIA_BITBLT_MONO) 1548c2ecf20Sopenharmony_ci ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000; 1558c2ecf20Sopenharmony_ci else 1568c2ecf20Sopenharmony_ci ge_cmd |= 0x00000001; 1578c2ecf20Sopenharmony_ci } 1588c2ecf20Sopenharmony_ci writel(ge_cmd, engine); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci if (op == VIA_BITBLT_FILL || !src_mem) 1618c2ecf20Sopenharmony_ci return 0; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) + 1648c2ecf20Sopenharmony_ci 3) >> 2; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci for (i = 0; i < tmp; i++) 1678c2ecf20Sopenharmony_ci writel(src_mem[i], engine + VIA_MMIO_BLTBASE); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci return 0; 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistatic int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height, 1738c2ecf20Sopenharmony_ci u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y, 1748c2ecf20Sopenharmony_ci u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y, 1758c2ecf20Sopenharmony_ci u32 fg_color, u32 bg_color, u8 fill_rop) 1768c2ecf20Sopenharmony_ci{ 1778c2ecf20Sopenharmony_ci u32 ge_cmd = 0, tmp, i; 1788c2ecf20Sopenharmony_ci int ret; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci if (!op || op > 3) { 1818c2ecf20Sopenharmony_ci printk(KERN_WARNING "hw_bitblt_2: Invalid operation: %d\n", op); 1828c2ecf20Sopenharmony_ci return -EINVAL; 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) { 1868c2ecf20Sopenharmony_ci if (src_x < dst_x) { 1878c2ecf20Sopenharmony_ci ge_cmd |= 0x00008000; 1888c2ecf20Sopenharmony_ci src_x += width - 1; 1898c2ecf20Sopenharmony_ci dst_x += width - 1; 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci if (src_y < dst_y) { 1928c2ecf20Sopenharmony_ci ge_cmd |= 0x00004000; 1938c2ecf20Sopenharmony_ci src_y += height - 1; 1948c2ecf20Sopenharmony_ci dst_y += height - 1; 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci if (op == VIA_BITBLT_FILL) { 1998c2ecf20Sopenharmony_ci switch (fill_rop) { 2008c2ecf20Sopenharmony_ci case 0x00: /* blackness */ 2018c2ecf20Sopenharmony_ci case 0x5A: /* pattern inversion */ 2028c2ecf20Sopenharmony_ci case 0xF0: /* pattern copy */ 2038c2ecf20Sopenharmony_ci case 0xFF: /* whiteness */ 2048c2ecf20Sopenharmony_ci break; 2058c2ecf20Sopenharmony_ci default: 2068c2ecf20Sopenharmony_ci printk(KERN_WARNING "hw_bitblt_2: Invalid fill rop: " 2078c2ecf20Sopenharmony_ci "%u\n", fill_rop); 2088c2ecf20Sopenharmony_ci return -EINVAL; 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci ret = viafb_set_bpp(engine, dst_bpp); 2138c2ecf20Sopenharmony_ci if (ret) 2148c2ecf20Sopenharmony_ci return ret; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci if (op == VIA_BITBLT_FILL) 2178c2ecf20Sopenharmony_ci tmp = 0; 2188c2ecf20Sopenharmony_ci else 2198c2ecf20Sopenharmony_ci tmp = src_pitch; 2208c2ecf20Sopenharmony_ci if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) { 2218c2ecf20Sopenharmony_ci printk(KERN_WARNING "hw_bitblt_2: Unsupported pitch %X %X\n", 2228c2ecf20Sopenharmony_ci tmp, dst_pitch); 2238c2ecf20Sopenharmony_ci return -EINVAL; 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci tmp = (tmp >> 3) | (dst_pitch << (16 - 3)); 2268c2ecf20Sopenharmony_ci writel(tmp, engine + 0x08); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) { 2298c2ecf20Sopenharmony_ci printk(KERN_WARNING "hw_bitblt_2: Unsupported width/height " 2308c2ecf20Sopenharmony_ci "%d %d\n", width, height); 2318c2ecf20Sopenharmony_ci return -EINVAL; 2328c2ecf20Sopenharmony_ci } 2338c2ecf20Sopenharmony_ci tmp = (width - 1) | ((height - 1) << 16); 2348c2ecf20Sopenharmony_ci writel(tmp, engine + 0x0C); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) { 2378c2ecf20Sopenharmony_ci printk(KERN_WARNING "hw_bitblt_2: Unsupported destination x/y " 2388c2ecf20Sopenharmony_ci "%d %d\n", dst_x, dst_y); 2398c2ecf20Sopenharmony_ci return -EINVAL; 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci tmp = dst_x | (dst_y << 16); 2428c2ecf20Sopenharmony_ci writel(tmp, engine + 0x10); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci if (dst_addr & 0xE0000007) { 2458c2ecf20Sopenharmony_ci printk(KERN_WARNING "hw_bitblt_2: Unsupported destination " 2468c2ecf20Sopenharmony_ci "address %X\n", dst_addr); 2478c2ecf20Sopenharmony_ci return -EINVAL; 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci tmp = dst_addr >> 3; 2508c2ecf20Sopenharmony_ci writel(tmp, engine + 0x14); 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci if (op != VIA_BITBLT_FILL) { 2538c2ecf20Sopenharmony_ci if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000) 2548c2ecf20Sopenharmony_ci || src_y & 0xFFFFF000) { 2558c2ecf20Sopenharmony_ci printk(KERN_WARNING "hw_bitblt_2: Unsupported source " 2568c2ecf20Sopenharmony_ci "x/y %d %d\n", src_x, src_y); 2578c2ecf20Sopenharmony_ci return -EINVAL; 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci tmp = src_x | (src_y << 16); 2608c2ecf20Sopenharmony_ci writel(tmp, engine + 0x18); 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci tmp = src_mem ? 0 : src_addr; 2638c2ecf20Sopenharmony_ci if (dst_addr & 0xE0000007) { 2648c2ecf20Sopenharmony_ci printk(KERN_WARNING "hw_bitblt_2: Unsupported source " 2658c2ecf20Sopenharmony_ci "address %X\n", tmp); 2668c2ecf20Sopenharmony_ci return -EINVAL; 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci tmp >>= 3; 2698c2ecf20Sopenharmony_ci writel(tmp, engine + 0x1C); 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci if (op == VIA_BITBLT_FILL) { 2738c2ecf20Sopenharmony_ci writel(fg_color, engine + 0x58); 2748c2ecf20Sopenharmony_ci } else if (op == VIA_BITBLT_MONO) { 2758c2ecf20Sopenharmony_ci writel(fg_color, engine + 0x4C); 2768c2ecf20Sopenharmony_ci writel(bg_color, engine + 0x50); 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci if (op == VIA_BITBLT_FILL) 2808c2ecf20Sopenharmony_ci ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001; 2818c2ecf20Sopenharmony_ci else { 2828c2ecf20Sopenharmony_ci ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */ 2838c2ecf20Sopenharmony_ci if (src_mem) 2848c2ecf20Sopenharmony_ci ge_cmd |= 0x00000040; 2858c2ecf20Sopenharmony_ci if (op == VIA_BITBLT_MONO) 2868c2ecf20Sopenharmony_ci ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000; 2878c2ecf20Sopenharmony_ci else 2888c2ecf20Sopenharmony_ci ge_cmd |= 0x00000001; 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci writel(ge_cmd, engine); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci if (op == VIA_BITBLT_FILL || !src_mem) 2938c2ecf20Sopenharmony_ci return 0; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) + 2968c2ecf20Sopenharmony_ci 3) >> 2; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci for (i = 0; i < tmp; i++) 2998c2ecf20Sopenharmony_ci writel(src_mem[i], engine + VIA_MMIO_BLTBASE); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci return 0; 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ciint viafb_setup_engine(struct fb_info *info) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci struct viafb_par *viapar = info->par; 3078c2ecf20Sopenharmony_ci void __iomem *engine; 3088c2ecf20Sopenharmony_ci u32 chip_name = viapar->shared->chip_info.gfx_chip_name; 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci engine = viapar->shared->vdev->engine_mmio; 3118c2ecf20Sopenharmony_ci if (!engine) { 3128c2ecf20Sopenharmony_ci printk(KERN_WARNING "viafb_init_accel: ioremap failed, " 3138c2ecf20Sopenharmony_ci "hardware acceleration disabled\n"); 3148c2ecf20Sopenharmony_ci return -ENOMEM; 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci switch (chip_name) { 3188c2ecf20Sopenharmony_ci case UNICHROME_CLE266: 3198c2ecf20Sopenharmony_ci case UNICHROME_K400: 3208c2ecf20Sopenharmony_ci case UNICHROME_K800: 3218c2ecf20Sopenharmony_ci case UNICHROME_PM800: 3228c2ecf20Sopenharmony_ci case UNICHROME_CN700: 3238c2ecf20Sopenharmony_ci case UNICHROME_CX700: 3248c2ecf20Sopenharmony_ci case UNICHROME_CN750: 3258c2ecf20Sopenharmony_ci case UNICHROME_K8M890: 3268c2ecf20Sopenharmony_ci case UNICHROME_P4M890: 3278c2ecf20Sopenharmony_ci case UNICHROME_P4M900: 3288c2ecf20Sopenharmony_ci viapar->shared->hw_bitblt = hw_bitblt_1; 3298c2ecf20Sopenharmony_ci break; 3308c2ecf20Sopenharmony_ci case UNICHROME_VX800: 3318c2ecf20Sopenharmony_ci case UNICHROME_VX855: 3328c2ecf20Sopenharmony_ci case UNICHROME_VX900: 3338c2ecf20Sopenharmony_ci viapar->shared->hw_bitblt = hw_bitblt_2; 3348c2ecf20Sopenharmony_ci break; 3358c2ecf20Sopenharmony_ci default: 3368c2ecf20Sopenharmony_ci viapar->shared->hw_bitblt = NULL; 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci viapar->fbmem_free -= CURSOR_SIZE; 3408c2ecf20Sopenharmony_ci viapar->shared->cursor_vram_addr = viapar->fbmem_free; 3418c2ecf20Sopenharmony_ci viapar->fbmem_used += CURSOR_SIZE; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci viapar->fbmem_free -= VQ_SIZE; 3448c2ecf20Sopenharmony_ci viapar->shared->vq_vram_addr = viapar->fbmem_free; 3458c2ecf20Sopenharmony_ci viapar->fbmem_used += VQ_SIZE; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_VIDEO_VIA_CAMERA) 3488c2ecf20Sopenharmony_ci /* 3498c2ecf20Sopenharmony_ci * Set aside a chunk of framebuffer memory for the camera 3508c2ecf20Sopenharmony_ci * driver. Someday this driver probably needs a proper allocator 3518c2ecf20Sopenharmony_ci * for fbmem; for now, we just have to do this before the 3528c2ecf20Sopenharmony_ci * framebuffer initializes itself. 3538c2ecf20Sopenharmony_ci * 3548c2ecf20Sopenharmony_ci * As for the size: the engine can handle three frames, 3558c2ecf20Sopenharmony_ci * 16 bits deep, up to VGA resolution. 3568c2ecf20Sopenharmony_ci */ 3578c2ecf20Sopenharmony_ci viapar->shared->vdev->camera_fbmem_size = 3*VGA_HEIGHT*VGA_WIDTH*2; 3588c2ecf20Sopenharmony_ci viapar->fbmem_free -= viapar->shared->vdev->camera_fbmem_size; 3598c2ecf20Sopenharmony_ci viapar->fbmem_used += viapar->shared->vdev->camera_fbmem_size; 3608c2ecf20Sopenharmony_ci viapar->shared->vdev->camera_fbmem_offset = viapar->fbmem_free; 3618c2ecf20Sopenharmony_ci#endif 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci viafb_reset_engine(viapar); 3648c2ecf20Sopenharmony_ci return 0; 3658c2ecf20Sopenharmony_ci} 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_civoid viafb_reset_engine(struct viafb_par *viapar) 3688c2ecf20Sopenharmony_ci{ 3698c2ecf20Sopenharmony_ci void __iomem *engine = viapar->shared->vdev->engine_mmio; 3708c2ecf20Sopenharmony_ci int highest_reg, i; 3718c2ecf20Sopenharmony_ci u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high, 3728c2ecf20Sopenharmony_ci vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci /* Initialize registers to reset the 2D engine */ 3758c2ecf20Sopenharmony_ci switch (viapar->shared->chip_info.twod_engine) { 3768c2ecf20Sopenharmony_ci case VIA_2D_ENG_M1: 3778c2ecf20Sopenharmony_ci highest_reg = 0x5c; 3788c2ecf20Sopenharmony_ci break; 3798c2ecf20Sopenharmony_ci default: 3808c2ecf20Sopenharmony_ci highest_reg = 0x40; 3818c2ecf20Sopenharmony_ci break; 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci for (i = 0; i <= highest_reg; i += 4) 3848c2ecf20Sopenharmony_ci writel(0x0, engine + i); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci /* Init AGP and VQ regs */ 3878c2ecf20Sopenharmony_ci switch (chip_name) { 3888c2ecf20Sopenharmony_ci case UNICHROME_K8M890: 3898c2ecf20Sopenharmony_ci case UNICHROME_P4M900: 3908c2ecf20Sopenharmony_ci case UNICHROME_VX800: 3918c2ecf20Sopenharmony_ci case UNICHROME_VX855: 3928c2ecf20Sopenharmony_ci case UNICHROME_VX900: 3938c2ecf20Sopenharmony_ci writel(0x00100000, engine + VIA_REG_CR_TRANSET); 3948c2ecf20Sopenharmony_ci writel(0x680A0000, engine + VIA_REG_CR_TRANSPACE); 3958c2ecf20Sopenharmony_ci writel(0x02000000, engine + VIA_REG_CR_TRANSPACE); 3968c2ecf20Sopenharmony_ci break; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci default: 3998c2ecf20Sopenharmony_ci writel(0x00100000, engine + VIA_REG_TRANSET); 4008c2ecf20Sopenharmony_ci writel(0x00000000, engine + VIA_REG_TRANSPACE); 4018c2ecf20Sopenharmony_ci writel(0x00333004, engine + VIA_REG_TRANSPACE); 4028c2ecf20Sopenharmony_ci writel(0x60000000, engine + VIA_REG_TRANSPACE); 4038c2ecf20Sopenharmony_ci writel(0x61000000, engine + VIA_REG_TRANSPACE); 4048c2ecf20Sopenharmony_ci writel(0x62000000, engine + VIA_REG_TRANSPACE); 4058c2ecf20Sopenharmony_ci writel(0x63000000, engine + VIA_REG_TRANSPACE); 4068c2ecf20Sopenharmony_ci writel(0x64000000, engine + VIA_REG_TRANSPACE); 4078c2ecf20Sopenharmony_ci writel(0x7D000000, engine + VIA_REG_TRANSPACE); 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci writel(0xFE020000, engine + VIA_REG_TRANSET); 4108c2ecf20Sopenharmony_ci writel(0x00000000, engine + VIA_REG_TRANSPACE); 4118c2ecf20Sopenharmony_ci break; 4128c2ecf20Sopenharmony_ci } 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci /* Enable VQ */ 4158c2ecf20Sopenharmony_ci vq_start_addr = viapar->shared->vq_vram_addr; 4168c2ecf20Sopenharmony_ci vq_end_addr = viapar->shared->vq_vram_addr + VQ_SIZE - 1; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci vq_start_low = 0x50000000 | (vq_start_addr & 0xFFFFFF); 4198c2ecf20Sopenharmony_ci vq_end_low = 0x51000000 | (vq_end_addr & 0xFFFFFF); 4208c2ecf20Sopenharmony_ci vq_high = 0x52000000 | ((vq_start_addr & 0xFF000000) >> 24) | 4218c2ecf20Sopenharmony_ci ((vq_end_addr & 0xFF000000) >> 16); 4228c2ecf20Sopenharmony_ci vq_len = 0x53000000 | (VQ_SIZE >> 3); 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci switch (chip_name) { 4258c2ecf20Sopenharmony_ci case UNICHROME_K8M890: 4268c2ecf20Sopenharmony_ci case UNICHROME_P4M900: 4278c2ecf20Sopenharmony_ci case UNICHROME_VX800: 4288c2ecf20Sopenharmony_ci case UNICHROME_VX855: 4298c2ecf20Sopenharmony_ci case UNICHROME_VX900: 4308c2ecf20Sopenharmony_ci vq_start_low |= 0x20000000; 4318c2ecf20Sopenharmony_ci vq_end_low |= 0x20000000; 4328c2ecf20Sopenharmony_ci vq_high |= 0x20000000; 4338c2ecf20Sopenharmony_ci vq_len |= 0x20000000; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci writel(0x00100000, engine + VIA_REG_CR_TRANSET); 4368c2ecf20Sopenharmony_ci writel(vq_high, engine + VIA_REG_CR_TRANSPACE); 4378c2ecf20Sopenharmony_ci writel(vq_start_low, engine + VIA_REG_CR_TRANSPACE); 4388c2ecf20Sopenharmony_ci writel(vq_end_low, engine + VIA_REG_CR_TRANSPACE); 4398c2ecf20Sopenharmony_ci writel(vq_len, engine + VIA_REG_CR_TRANSPACE); 4408c2ecf20Sopenharmony_ci writel(0x74301001, engine + VIA_REG_CR_TRANSPACE); 4418c2ecf20Sopenharmony_ci writel(0x00000000, engine + VIA_REG_CR_TRANSPACE); 4428c2ecf20Sopenharmony_ci break; 4438c2ecf20Sopenharmony_ci default: 4448c2ecf20Sopenharmony_ci writel(0x00FE0000, engine + VIA_REG_TRANSET); 4458c2ecf20Sopenharmony_ci writel(0x080003FE, engine + VIA_REG_TRANSPACE); 4468c2ecf20Sopenharmony_ci writel(0x0A00027C, engine + VIA_REG_TRANSPACE); 4478c2ecf20Sopenharmony_ci writel(0x0B000260, engine + VIA_REG_TRANSPACE); 4488c2ecf20Sopenharmony_ci writel(0x0C000274, engine + VIA_REG_TRANSPACE); 4498c2ecf20Sopenharmony_ci writel(0x0D000264, engine + VIA_REG_TRANSPACE); 4508c2ecf20Sopenharmony_ci writel(0x0E000000, engine + VIA_REG_TRANSPACE); 4518c2ecf20Sopenharmony_ci writel(0x0F000020, engine + VIA_REG_TRANSPACE); 4528c2ecf20Sopenharmony_ci writel(0x1000027E, engine + VIA_REG_TRANSPACE); 4538c2ecf20Sopenharmony_ci writel(0x110002FE, engine + VIA_REG_TRANSPACE); 4548c2ecf20Sopenharmony_ci writel(0x200F0060, engine + VIA_REG_TRANSPACE); 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci writel(0x00000006, engine + VIA_REG_TRANSPACE); 4578c2ecf20Sopenharmony_ci writel(0x40008C0F, engine + VIA_REG_TRANSPACE); 4588c2ecf20Sopenharmony_ci writel(0x44000000, engine + VIA_REG_TRANSPACE); 4598c2ecf20Sopenharmony_ci writel(0x45080C04, engine + VIA_REG_TRANSPACE); 4608c2ecf20Sopenharmony_ci writel(0x46800408, engine + VIA_REG_TRANSPACE); 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci writel(vq_high, engine + VIA_REG_TRANSPACE); 4638c2ecf20Sopenharmony_ci writel(vq_start_low, engine + VIA_REG_TRANSPACE); 4648c2ecf20Sopenharmony_ci writel(vq_end_low, engine + VIA_REG_TRANSPACE); 4658c2ecf20Sopenharmony_ci writel(vq_len, engine + VIA_REG_TRANSPACE); 4668c2ecf20Sopenharmony_ci break; 4678c2ecf20Sopenharmony_ci } 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci /* Set Cursor Image Base Address */ 4708c2ecf20Sopenharmony_ci writel(viapar->shared->cursor_vram_addr, engine + VIA_REG_CURSOR_MODE); 4718c2ecf20Sopenharmony_ci writel(0x0, engine + VIA_REG_CURSOR_POS); 4728c2ecf20Sopenharmony_ci writel(0x0, engine + VIA_REG_CURSOR_ORG); 4738c2ecf20Sopenharmony_ci writel(0x0, engine + VIA_REG_CURSOR_BG); 4748c2ecf20Sopenharmony_ci writel(0x0, engine + VIA_REG_CURSOR_FG); 4758c2ecf20Sopenharmony_ci return; 4768c2ecf20Sopenharmony_ci} 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_civoid viafb_show_hw_cursor(struct fb_info *info, int Status) 4798c2ecf20Sopenharmony_ci{ 4808c2ecf20Sopenharmony_ci struct viafb_par *viapar = info->par; 4818c2ecf20Sopenharmony_ci u32 temp, iga_path = viapar->iga_path; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci temp = readl(viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE); 4848c2ecf20Sopenharmony_ci switch (Status) { 4858c2ecf20Sopenharmony_ci case HW_Cursor_ON: 4868c2ecf20Sopenharmony_ci temp |= 0x1; 4878c2ecf20Sopenharmony_ci break; 4888c2ecf20Sopenharmony_ci case HW_Cursor_OFF: 4898c2ecf20Sopenharmony_ci temp &= 0xFFFFFFFE; 4908c2ecf20Sopenharmony_ci break; 4918c2ecf20Sopenharmony_ci } 4928c2ecf20Sopenharmony_ci switch (iga_path) { 4938c2ecf20Sopenharmony_ci case IGA2: 4948c2ecf20Sopenharmony_ci temp |= 0x80000000; 4958c2ecf20Sopenharmony_ci break; 4968c2ecf20Sopenharmony_ci case IGA1: 4978c2ecf20Sopenharmony_ci default: 4988c2ecf20Sopenharmony_ci temp &= 0x7FFFFFFF; 4998c2ecf20Sopenharmony_ci } 5008c2ecf20Sopenharmony_ci writel(temp, viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE); 5018c2ecf20Sopenharmony_ci} 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_civoid viafb_wait_engine_idle(struct fb_info *info) 5048c2ecf20Sopenharmony_ci{ 5058c2ecf20Sopenharmony_ci struct viafb_par *viapar = info->par; 5068c2ecf20Sopenharmony_ci int loop = 0; 5078c2ecf20Sopenharmony_ci u32 mask; 5088c2ecf20Sopenharmony_ci void __iomem *engine = viapar->shared->vdev->engine_mmio; 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci switch (viapar->shared->chip_info.twod_engine) { 5118c2ecf20Sopenharmony_ci case VIA_2D_ENG_H5: 5128c2ecf20Sopenharmony_ci case VIA_2D_ENG_M1: 5138c2ecf20Sopenharmony_ci mask = VIA_CMD_RGTR_BUSY_M1 | VIA_2D_ENG_BUSY_M1 | 5148c2ecf20Sopenharmony_ci VIA_3D_ENG_BUSY_M1; 5158c2ecf20Sopenharmony_ci break; 5168c2ecf20Sopenharmony_ci default: 5178c2ecf20Sopenharmony_ci while (!(readl(engine + VIA_REG_STATUS) & 5188c2ecf20Sopenharmony_ci VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) { 5198c2ecf20Sopenharmony_ci loop++; 5208c2ecf20Sopenharmony_ci cpu_relax(); 5218c2ecf20Sopenharmony_ci } 5228c2ecf20Sopenharmony_ci mask = VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY; 5238c2ecf20Sopenharmony_ci break; 5248c2ecf20Sopenharmony_ci } 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci while ((readl(engine + VIA_REG_STATUS) & mask) && (loop < MAXLOOP)) { 5278c2ecf20Sopenharmony_ci loop++; 5288c2ecf20Sopenharmony_ci cpu_relax(); 5298c2ecf20Sopenharmony_ci } 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci if (loop >= MAXLOOP) 5328c2ecf20Sopenharmony_ci printk(KERN_ERR "viafb_wait_engine_idle: not syncing\n"); 5338c2ecf20Sopenharmony_ci} 534