^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/via-core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "global.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Figure out an appropriate bytes-per-pixel setting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) static int viafb_set_bpp(void __iomem *engine, u8 bpp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) u32 gemode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /* Preserve the reserved bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /* Lowest 2 bits to zero gives us no rotation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) gemode = readl(engine + VIA_REG_GEMODE) & 0xfffffcfc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) switch (bpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) gemode |= VIA_GEM_8bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) gemode |= VIA_GEM_16bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) gemode |= VIA_GEM_32bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) printk(KERN_WARNING "viafb_set_bpp: Unsupported bpp %d\n", bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) writel(gemode, engine + VIA_REG_GEMODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) u32 fg_color, u32 bg_color, u8 fill_rop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) u32 ge_cmd = 0, tmp, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (!op || op > 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) printk(KERN_WARNING "hw_bitblt_1: Invalid operation: %d\n", op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (src_x < dst_x) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) ge_cmd |= 0x00008000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) src_x += width - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) dst_x += width - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (src_y < dst_y) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) ge_cmd |= 0x00004000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) src_y += height - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) dst_y += height - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (op == VIA_BITBLT_FILL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) switch (fill_rop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) case 0x00: /* blackness */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) case 0x5A: /* pattern inversion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) case 0xF0: /* pattern copy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) case 0xFF: /* whiteness */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) printk(KERN_WARNING "hw_bitblt_1: Invalid fill rop: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) "%u\n", fill_rop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) ret = viafb_set_bpp(engine, dst_bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (op != VIA_BITBLT_FILL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) || src_y & 0xFFFFF000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) printk(KERN_WARNING "hw_bitblt_1: Unsupported source "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) "x/y %d %d\n", src_x, src_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) tmp = src_x | (src_y << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) writel(tmp, engine + 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) printk(KERN_WARNING "hw_bitblt_1: Unsupported destination x/y "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) "%d %d\n", dst_x, dst_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) tmp = dst_x | (dst_y << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) writel(tmp, engine + 0x0C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) printk(KERN_WARNING "hw_bitblt_1: Unsupported width/height "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) "%d %d\n", width, height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) tmp = (width - 1) | ((height - 1) << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) writel(tmp, engine + 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (op != VIA_BITBLT_COLOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) writel(fg_color, engine + 0x18);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (op == VIA_BITBLT_MONO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) writel(bg_color, engine + 0x1C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (op != VIA_BITBLT_FILL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) tmp = src_mem ? 0 : src_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (dst_addr & 0xE0000007) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) printk(KERN_WARNING "hw_bitblt_1: Unsupported source "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) "address %X\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) tmp >>= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) writel(tmp, engine + 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (dst_addr & 0xE0000007) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) printk(KERN_WARNING "hw_bitblt_1: Unsupported destination "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) "address %X\n", dst_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) tmp = dst_addr >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) writel(tmp, engine + 0x34);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (op == VIA_BITBLT_FILL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) tmp = src_pitch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) printk(KERN_WARNING "hw_bitblt_1: Unsupported pitch %X %X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) tmp, dst_pitch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) tmp = VIA_PITCH_ENABLE | (tmp >> 3) | (dst_pitch << (16 - 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) writel(tmp, engine + 0x38);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (op == VIA_BITBLT_FILL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (src_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ge_cmd |= 0x00000040;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (op == VIA_BITBLT_MONO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) ge_cmd |= 0x00000001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) writel(ge_cmd, engine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (op == VIA_BITBLT_FILL || !src_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 3) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) for (i = 0; i < tmp; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) writel(src_mem[i], engine + VIA_MMIO_BLTBASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) u32 fg_color, u32 bg_color, u8 fill_rop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) u32 ge_cmd = 0, tmp, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (!op || op > 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) printk(KERN_WARNING "hw_bitblt_2: Invalid operation: %d\n", op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (src_x < dst_x) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) ge_cmd |= 0x00008000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) src_x += width - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) dst_x += width - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (src_y < dst_y) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ge_cmd |= 0x00004000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) src_y += height - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) dst_y += height - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (op == VIA_BITBLT_FILL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) switch (fill_rop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) case 0x00: /* blackness */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) case 0x5A: /* pattern inversion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) case 0xF0: /* pattern copy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) case 0xFF: /* whiteness */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) printk(KERN_WARNING "hw_bitblt_2: Invalid fill rop: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) "%u\n", fill_rop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ret = viafb_set_bpp(engine, dst_bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (op == VIA_BITBLT_FILL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) tmp = src_pitch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) printk(KERN_WARNING "hw_bitblt_2: Unsupported pitch %X %X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) tmp, dst_pitch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) tmp = (tmp >> 3) | (dst_pitch << (16 - 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) writel(tmp, engine + 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) printk(KERN_WARNING "hw_bitblt_2: Unsupported width/height "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) "%d %d\n", width, height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) tmp = (width - 1) | ((height - 1) << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) writel(tmp, engine + 0x0C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) printk(KERN_WARNING "hw_bitblt_2: Unsupported destination x/y "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) "%d %d\n", dst_x, dst_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) tmp = dst_x | (dst_y << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) writel(tmp, engine + 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (dst_addr & 0xE0000007) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) printk(KERN_WARNING "hw_bitblt_2: Unsupported destination "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) "address %X\n", dst_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) tmp = dst_addr >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) writel(tmp, engine + 0x14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (op != VIA_BITBLT_FILL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) || src_y & 0xFFFFF000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) printk(KERN_WARNING "hw_bitblt_2: Unsupported source "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) "x/y %d %d\n", src_x, src_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) tmp = src_x | (src_y << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) writel(tmp, engine + 0x18);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) tmp = src_mem ? 0 : src_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (dst_addr & 0xE0000007) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) printk(KERN_WARNING "hw_bitblt_2: Unsupported source "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) "address %X\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) tmp >>= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) writel(tmp, engine + 0x1C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (op == VIA_BITBLT_FILL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) writel(fg_color, engine + 0x58);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) } else if (op == VIA_BITBLT_MONO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) writel(fg_color, engine + 0x4C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) writel(bg_color, engine + 0x50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (op == VIA_BITBLT_FILL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (src_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) ge_cmd |= 0x00000040;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (op == VIA_BITBLT_MONO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) ge_cmd |= 0x00000001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) writel(ge_cmd, engine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (op == VIA_BITBLT_FILL || !src_mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 3) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) for (i = 0; i < tmp; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) writel(src_mem[i], engine + VIA_MMIO_BLTBASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) int viafb_setup_engine(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct viafb_par *viapar = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) void __iomem *engine;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) u32 chip_name = viapar->shared->chip_info.gfx_chip_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) engine = viapar->shared->vdev->engine_mmio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (!engine) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) printk(KERN_WARNING "viafb_init_accel: ioremap failed, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) "hardware acceleration disabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) switch (chip_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) case UNICHROME_CLE266:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) case UNICHROME_K400:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) case UNICHROME_K800:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) case UNICHROME_PM800:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) case UNICHROME_CN700:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) case UNICHROME_CX700:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) case UNICHROME_CN750:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) case UNICHROME_K8M890:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) case UNICHROME_P4M890:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) case UNICHROME_P4M900:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) viapar->shared->hw_bitblt = hw_bitblt_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) case UNICHROME_VX800:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) case UNICHROME_VX855:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) case UNICHROME_VX900:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) viapar->shared->hw_bitblt = hw_bitblt_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) viapar->shared->hw_bitblt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) viapar->fbmem_free -= CURSOR_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) viapar->shared->cursor_vram_addr = viapar->fbmem_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) viapar->fbmem_used += CURSOR_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) viapar->fbmem_free -= VQ_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) viapar->shared->vq_vram_addr = viapar->fbmem_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) viapar->fbmem_used += VQ_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) #if IS_ENABLED(CONFIG_VIDEO_VIA_CAMERA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * Set aside a chunk of framebuffer memory for the camera
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) * driver. Someday this driver probably needs a proper allocator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * for fbmem; for now, we just have to do this before the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * framebuffer initializes itself.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * As for the size: the engine can handle three frames,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * 16 bits deep, up to VGA resolution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) viapar->shared->vdev->camera_fbmem_size = 3*VGA_HEIGHT*VGA_WIDTH*2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) viapar->fbmem_free -= viapar->shared->vdev->camera_fbmem_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) viapar->fbmem_used += viapar->shared->vdev->camera_fbmem_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) viapar->shared->vdev->camera_fbmem_offset = viapar->fbmem_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) viafb_reset_engine(viapar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) void viafb_reset_engine(struct viafb_par *viapar)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) void __iomem *engine = viapar->shared->vdev->engine_mmio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) int highest_reg, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /* Initialize registers to reset the 2D engine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) switch (viapar->shared->chip_info.twod_engine) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) case VIA_2D_ENG_M1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) highest_reg = 0x5c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) highest_reg = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) for (i = 0; i <= highest_reg; i += 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) writel(0x0, engine + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /* Init AGP and VQ regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) switch (chip_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) case UNICHROME_K8M890:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) case UNICHROME_P4M900:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) case UNICHROME_VX800:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) case UNICHROME_VX855:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) case UNICHROME_VX900:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) writel(0x00100000, engine + VIA_REG_CR_TRANSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) writel(0x680A0000, engine + VIA_REG_CR_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) writel(0x02000000, engine + VIA_REG_CR_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) writel(0x00100000, engine + VIA_REG_TRANSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) writel(0x00000000, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) writel(0x00333004, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) writel(0x60000000, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) writel(0x61000000, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) writel(0x62000000, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) writel(0x63000000, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) writel(0x64000000, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) writel(0x7D000000, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) writel(0xFE020000, engine + VIA_REG_TRANSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) writel(0x00000000, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) /* Enable VQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) vq_start_addr = viapar->shared->vq_vram_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) vq_end_addr = viapar->shared->vq_vram_addr + VQ_SIZE - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) vq_start_low = 0x50000000 | (vq_start_addr & 0xFFFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) vq_end_low = 0x51000000 | (vq_end_addr & 0xFFFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) vq_high = 0x52000000 | ((vq_start_addr & 0xFF000000) >> 24) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) ((vq_end_addr & 0xFF000000) >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) vq_len = 0x53000000 | (VQ_SIZE >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) switch (chip_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) case UNICHROME_K8M890:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) case UNICHROME_P4M900:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) case UNICHROME_VX800:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) case UNICHROME_VX855:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) case UNICHROME_VX900:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) vq_start_low |= 0x20000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) vq_end_low |= 0x20000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) vq_high |= 0x20000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) vq_len |= 0x20000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) writel(0x00100000, engine + VIA_REG_CR_TRANSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) writel(vq_high, engine + VIA_REG_CR_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) writel(vq_start_low, engine + VIA_REG_CR_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) writel(vq_end_low, engine + VIA_REG_CR_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) writel(vq_len, engine + VIA_REG_CR_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) writel(0x74301001, engine + VIA_REG_CR_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) writel(0x00000000, engine + VIA_REG_CR_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) writel(0x00FE0000, engine + VIA_REG_TRANSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) writel(0x080003FE, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) writel(0x0A00027C, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) writel(0x0B000260, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) writel(0x0C000274, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) writel(0x0D000264, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) writel(0x0E000000, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) writel(0x0F000020, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) writel(0x1000027E, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) writel(0x110002FE, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) writel(0x200F0060, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) writel(0x00000006, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) writel(0x40008C0F, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) writel(0x44000000, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) writel(0x45080C04, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) writel(0x46800408, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) writel(vq_high, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) writel(vq_start_low, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) writel(vq_end_low, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) writel(vq_len, engine + VIA_REG_TRANSPACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /* Set Cursor Image Base Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) writel(viapar->shared->cursor_vram_addr, engine + VIA_REG_CURSOR_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) writel(0x0, engine + VIA_REG_CURSOR_POS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) writel(0x0, engine + VIA_REG_CURSOR_ORG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) writel(0x0, engine + VIA_REG_CURSOR_BG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) writel(0x0, engine + VIA_REG_CURSOR_FG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) void viafb_show_hw_cursor(struct fb_info *info, int Status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct viafb_par *viapar = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) u32 temp, iga_path = viapar->iga_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) temp = readl(viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) switch (Status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) case HW_Cursor_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) temp |= 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) case HW_Cursor_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) temp &= 0xFFFFFFFE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) switch (iga_path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) case IGA2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) temp |= 0x80000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) case IGA1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) temp &= 0x7FFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) writel(temp, viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) void viafb_wait_engine_idle(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) struct viafb_par *viapar = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) int loop = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) void __iomem *engine = viapar->shared->vdev->engine_mmio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) switch (viapar->shared->chip_info.twod_engine) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) case VIA_2D_ENG_H5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) case VIA_2D_ENG_M1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) mask = VIA_CMD_RGTR_BUSY_M1 | VIA_2D_ENG_BUSY_M1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) VIA_3D_ENG_BUSY_M1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) while (!(readl(engine + VIA_REG_STATUS) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) loop++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) mask = VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) while ((readl(engine + VIA_REG_STATUS) & mask) && (loop < MAXLOOP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) loop++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (loop >= MAXLOOP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) printk(KERN_ERR "viafb_wait_engine_idle: not syncing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }