0001
0002
0003
0004
0005
0006
0007 #include <linux/via-core.h>
0008 #include "global.h"
0009
0010
0011
0012
0013 static int viafb_set_bpp(void __iomem *engine, u8 bpp)
0014 {
0015 u32 gemode;
0016
0017
0018
0019 gemode = readl(engine + VIA_REG_GEMODE) & 0xfffffcfc;
0020 switch (bpp) {
0021 case 8:
0022 gemode |= VIA_GEM_8bpp;
0023 break;
0024 case 16:
0025 gemode |= VIA_GEM_16bpp;
0026 break;
0027 case 32:
0028 gemode |= VIA_GEM_32bpp;
0029 break;
0030 default:
0031 printk(KERN_WARNING "viafb_set_bpp: Unsupported bpp %d\n", bpp);
0032 return -EINVAL;
0033 }
0034 writel(gemode, engine + VIA_REG_GEMODE);
0035 return 0;
0036 }
0037
0038
0039 static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height,
0040 u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
0041 u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
0042 u32 fg_color, u32 bg_color, u8 fill_rop)
0043 {
0044 u32 ge_cmd = 0, tmp, i;
0045 int ret;
0046
0047 if (!op || op > 3) {
0048 printk(KERN_WARNING "hw_bitblt_1: Invalid operation: %d\n", op);
0049 return -EINVAL;
0050 }
0051
0052 if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) {
0053 if (src_x < dst_x) {
0054 ge_cmd |= 0x00008000;
0055 src_x += width - 1;
0056 dst_x += width - 1;
0057 }
0058 if (src_y < dst_y) {
0059 ge_cmd |= 0x00004000;
0060 src_y += height - 1;
0061 dst_y += height - 1;
0062 }
0063 }
0064
0065 if (op == VIA_BITBLT_FILL) {
0066 switch (fill_rop) {
0067 case 0x00:
0068 case 0x5A:
0069 case 0xF0:
0070 case 0xFF:
0071 break;
0072 default:
0073 printk(KERN_WARNING "hw_bitblt_1: Invalid fill rop: "
0074 "%u\n", fill_rop);
0075 return -EINVAL;
0076 }
0077 }
0078
0079 ret = viafb_set_bpp(engine, dst_bpp);
0080 if (ret)
0081 return ret;
0082
0083 if (op != VIA_BITBLT_FILL) {
0084 if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000)
0085 || src_y & 0xFFFFF000) {
0086 printk(KERN_WARNING "hw_bitblt_1: Unsupported source "
0087 "x/y %d %d\n", src_x, src_y);
0088 return -EINVAL;
0089 }
0090 tmp = src_x | (src_y << 16);
0091 writel(tmp, engine + 0x08);
0092 }
0093
0094 if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) {
0095 printk(KERN_WARNING "hw_bitblt_1: Unsupported destination x/y "
0096 "%d %d\n", dst_x, dst_y);
0097 return -EINVAL;
0098 }
0099 tmp = dst_x | (dst_y << 16);
0100 writel(tmp, engine + 0x0C);
0101
0102 if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) {
0103 printk(KERN_WARNING "hw_bitblt_1: Unsupported width/height "
0104 "%d %d\n", width, height);
0105 return -EINVAL;
0106 }
0107 tmp = (width - 1) | ((height - 1) << 16);
0108 writel(tmp, engine + 0x10);
0109
0110 if (op != VIA_BITBLT_COLOR)
0111 writel(fg_color, engine + 0x18);
0112
0113 if (op == VIA_BITBLT_MONO)
0114 writel(bg_color, engine + 0x1C);
0115
0116 if (op != VIA_BITBLT_FILL) {
0117 tmp = src_mem ? 0 : src_addr;
0118 if (dst_addr & 0xE0000007) {
0119 printk(KERN_WARNING "hw_bitblt_1: Unsupported source "
0120 "address %X\n", tmp);
0121 return -EINVAL;
0122 }
0123 tmp >>= 3;
0124 writel(tmp, engine + 0x30);
0125 }
0126
0127 if (dst_addr & 0xE0000007) {
0128 printk(KERN_WARNING "hw_bitblt_1: Unsupported destination "
0129 "address %X\n", dst_addr);
0130 return -EINVAL;
0131 }
0132 tmp = dst_addr >> 3;
0133 writel(tmp, engine + 0x34);
0134
0135 if (op == VIA_BITBLT_FILL)
0136 tmp = 0;
0137 else
0138 tmp = src_pitch;
0139 if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) {
0140 printk(KERN_WARNING "hw_bitblt_1: Unsupported pitch %X %X\n",
0141 tmp, dst_pitch);
0142 return -EINVAL;
0143 }
0144 tmp = VIA_PITCH_ENABLE | (tmp >> 3) | (dst_pitch << (16 - 3));
0145 writel(tmp, engine + 0x38);
0146
0147 if (op == VIA_BITBLT_FILL)
0148 ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
0149 else {
0150 ge_cmd |= 0xCC000000;
0151 if (src_mem)
0152 ge_cmd |= 0x00000040;
0153 if (op == VIA_BITBLT_MONO)
0154 ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000;
0155 else
0156 ge_cmd |= 0x00000001;
0157 }
0158 writel(ge_cmd, engine);
0159
0160 if (op == VIA_BITBLT_FILL || !src_mem)
0161 return 0;
0162
0163 tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) +
0164 3) >> 2;
0165
0166 for (i = 0; i < tmp; i++)
0167 writel(src_mem[i], engine + VIA_MMIO_BLTBASE);
0168
0169 return 0;
0170 }
0171
0172 static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height,
0173 u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
0174 u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
0175 u32 fg_color, u32 bg_color, u8 fill_rop)
0176 {
0177 u32 ge_cmd = 0, tmp, i;
0178 int ret;
0179
0180 if (!op || op > 3) {
0181 printk(KERN_WARNING "hw_bitblt_2: Invalid operation: %d\n", op);
0182 return -EINVAL;
0183 }
0184
0185 if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) {
0186 if (src_x < dst_x) {
0187 ge_cmd |= 0x00008000;
0188 src_x += width - 1;
0189 dst_x += width - 1;
0190 }
0191 if (src_y < dst_y) {
0192 ge_cmd |= 0x00004000;
0193 src_y += height - 1;
0194 dst_y += height - 1;
0195 }
0196 }
0197
0198 if (op == VIA_BITBLT_FILL) {
0199 switch (fill_rop) {
0200 case 0x00:
0201 case 0x5A:
0202 case 0xF0:
0203 case 0xFF:
0204 break;
0205 default:
0206 printk(KERN_WARNING "hw_bitblt_2: Invalid fill rop: "
0207 "%u\n", fill_rop);
0208 return -EINVAL;
0209 }
0210 }
0211
0212 ret = viafb_set_bpp(engine, dst_bpp);
0213 if (ret)
0214 return ret;
0215
0216 if (op == VIA_BITBLT_FILL)
0217 tmp = 0;
0218 else
0219 tmp = src_pitch;
0220 if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) {
0221 printk(KERN_WARNING "hw_bitblt_2: Unsupported pitch %X %X\n",
0222 tmp, dst_pitch);
0223 return -EINVAL;
0224 }
0225 tmp = (tmp >> 3) | (dst_pitch << (16 - 3));
0226 writel(tmp, engine + 0x08);
0227
0228 if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) {
0229 printk(KERN_WARNING "hw_bitblt_2: Unsupported width/height "
0230 "%d %d\n", width, height);
0231 return -EINVAL;
0232 }
0233 tmp = (width - 1) | ((height - 1) << 16);
0234 writel(tmp, engine + 0x0C);
0235
0236 if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) {
0237 printk(KERN_WARNING "hw_bitblt_2: Unsupported destination x/y "
0238 "%d %d\n", dst_x, dst_y);
0239 return -EINVAL;
0240 }
0241 tmp = dst_x | (dst_y << 16);
0242 writel(tmp, engine + 0x10);
0243
0244 if (dst_addr & 0xE0000007) {
0245 printk(KERN_WARNING "hw_bitblt_2: Unsupported destination "
0246 "address %X\n", dst_addr);
0247 return -EINVAL;
0248 }
0249 tmp = dst_addr >> 3;
0250 writel(tmp, engine + 0x14);
0251
0252 if (op != VIA_BITBLT_FILL) {
0253 if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000)
0254 || src_y & 0xFFFFF000) {
0255 printk(KERN_WARNING "hw_bitblt_2: Unsupported source "
0256 "x/y %d %d\n", src_x, src_y);
0257 return -EINVAL;
0258 }
0259 tmp = src_x | (src_y << 16);
0260 writel(tmp, engine + 0x18);
0261
0262 tmp = src_mem ? 0 : src_addr;
0263 if (dst_addr & 0xE0000007) {
0264 printk(KERN_WARNING "hw_bitblt_2: Unsupported source "
0265 "address %X\n", tmp);
0266 return -EINVAL;
0267 }
0268 tmp >>= 3;
0269 writel(tmp, engine + 0x1C);
0270 }
0271
0272 if (op == VIA_BITBLT_FILL) {
0273 writel(fg_color, engine + 0x58);
0274 } else if (op == VIA_BITBLT_MONO) {
0275 writel(fg_color, engine + 0x4C);
0276 writel(bg_color, engine + 0x50);
0277 }
0278
0279 if (op == VIA_BITBLT_FILL)
0280 ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
0281 else {
0282 ge_cmd |= 0xCC000000;
0283 if (src_mem)
0284 ge_cmd |= 0x00000040;
0285 if (op == VIA_BITBLT_MONO)
0286 ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000;
0287 else
0288 ge_cmd |= 0x00000001;
0289 }
0290 writel(ge_cmd, engine);
0291
0292 if (op == VIA_BITBLT_FILL || !src_mem)
0293 return 0;
0294
0295 tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) +
0296 3) >> 2;
0297
0298 for (i = 0; i < tmp; i++)
0299 writel(src_mem[i], engine + VIA_MMIO_BLTBASE);
0300
0301 return 0;
0302 }
0303
0304 int viafb_setup_engine(struct fb_info *info)
0305 {
0306 struct viafb_par *viapar = info->par;
0307 void __iomem *engine;
0308 u32 chip_name = viapar->shared->chip_info.gfx_chip_name;
0309
0310 engine = viapar->shared->vdev->engine_mmio;
0311 if (!engine) {
0312 printk(KERN_WARNING "viafb_init_accel: ioremap failed, "
0313 "hardware acceleration disabled\n");
0314 return -ENOMEM;
0315 }
0316
0317 switch (chip_name) {
0318 case UNICHROME_CLE266:
0319 case UNICHROME_K400:
0320 case UNICHROME_K800:
0321 case UNICHROME_PM800:
0322 case UNICHROME_CN700:
0323 case UNICHROME_CX700:
0324 case UNICHROME_CN750:
0325 case UNICHROME_K8M890:
0326 case UNICHROME_P4M890:
0327 case UNICHROME_P4M900:
0328 viapar->shared->hw_bitblt = hw_bitblt_1;
0329 break;
0330 case UNICHROME_VX800:
0331 case UNICHROME_VX855:
0332 case UNICHROME_VX900:
0333 viapar->shared->hw_bitblt = hw_bitblt_2;
0334 break;
0335 default:
0336 viapar->shared->hw_bitblt = NULL;
0337 }
0338
0339 viapar->fbmem_free -= CURSOR_SIZE;
0340 viapar->shared->cursor_vram_addr = viapar->fbmem_free;
0341 viapar->fbmem_used += CURSOR_SIZE;
0342
0343 viapar->fbmem_free -= VQ_SIZE;
0344 viapar->shared->vq_vram_addr = viapar->fbmem_free;
0345 viapar->fbmem_used += VQ_SIZE;
0346
0347 #if IS_ENABLED(CONFIG_VIDEO_VIA_CAMERA)
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357 viapar->shared->vdev->camera_fbmem_size = 3*VGA_HEIGHT*VGA_WIDTH*2;
0358 viapar->fbmem_free -= viapar->shared->vdev->camera_fbmem_size;
0359 viapar->fbmem_used += viapar->shared->vdev->camera_fbmem_size;
0360 viapar->shared->vdev->camera_fbmem_offset = viapar->fbmem_free;
0361 #endif
0362
0363 viafb_reset_engine(viapar);
0364 return 0;
0365 }
0366
0367 void viafb_reset_engine(struct viafb_par *viapar)
0368 {
0369 void __iomem *engine = viapar->shared->vdev->engine_mmio;
0370 int highest_reg, i;
0371 u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high,
0372 vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name;
0373
0374
0375 switch (viapar->shared->chip_info.twod_engine) {
0376 case VIA_2D_ENG_M1:
0377 highest_reg = 0x5c;
0378 break;
0379 default:
0380 highest_reg = 0x40;
0381 break;
0382 }
0383 for (i = 0; i <= highest_reg; i += 4)
0384 writel(0x0, engine + i);
0385
0386
0387 switch (chip_name) {
0388 case UNICHROME_K8M890:
0389 case UNICHROME_P4M900:
0390 case UNICHROME_VX800:
0391 case UNICHROME_VX855:
0392 case UNICHROME_VX900:
0393 writel(0x00100000, engine + VIA_REG_CR_TRANSET);
0394 writel(0x680A0000, engine + VIA_REG_CR_TRANSPACE);
0395 writel(0x02000000, engine + VIA_REG_CR_TRANSPACE);
0396 break;
0397
0398 default:
0399 writel(0x00100000, engine + VIA_REG_TRANSET);
0400 writel(0x00000000, engine + VIA_REG_TRANSPACE);
0401 writel(0x00333004, engine + VIA_REG_TRANSPACE);
0402 writel(0x60000000, engine + VIA_REG_TRANSPACE);
0403 writel(0x61000000, engine + VIA_REG_TRANSPACE);
0404 writel(0x62000000, engine + VIA_REG_TRANSPACE);
0405 writel(0x63000000, engine + VIA_REG_TRANSPACE);
0406 writel(0x64000000, engine + VIA_REG_TRANSPACE);
0407 writel(0x7D000000, engine + VIA_REG_TRANSPACE);
0408
0409 writel(0xFE020000, engine + VIA_REG_TRANSET);
0410 writel(0x00000000, engine + VIA_REG_TRANSPACE);
0411 break;
0412 }
0413
0414
0415 vq_start_addr = viapar->shared->vq_vram_addr;
0416 vq_end_addr = viapar->shared->vq_vram_addr + VQ_SIZE - 1;
0417
0418 vq_start_low = 0x50000000 | (vq_start_addr & 0xFFFFFF);
0419 vq_end_low = 0x51000000 | (vq_end_addr & 0xFFFFFF);
0420 vq_high = 0x52000000 | ((vq_start_addr & 0xFF000000) >> 24) |
0421 ((vq_end_addr & 0xFF000000) >> 16);
0422 vq_len = 0x53000000 | (VQ_SIZE >> 3);
0423
0424 switch (chip_name) {
0425 case UNICHROME_K8M890:
0426 case UNICHROME_P4M900:
0427 case UNICHROME_VX800:
0428 case UNICHROME_VX855:
0429 case UNICHROME_VX900:
0430 vq_start_low |= 0x20000000;
0431 vq_end_low |= 0x20000000;
0432 vq_high |= 0x20000000;
0433 vq_len |= 0x20000000;
0434
0435 writel(0x00100000, engine + VIA_REG_CR_TRANSET);
0436 writel(vq_high, engine + VIA_REG_CR_TRANSPACE);
0437 writel(vq_start_low, engine + VIA_REG_CR_TRANSPACE);
0438 writel(vq_end_low, engine + VIA_REG_CR_TRANSPACE);
0439 writel(vq_len, engine + VIA_REG_CR_TRANSPACE);
0440 writel(0x74301001, engine + VIA_REG_CR_TRANSPACE);
0441 writel(0x00000000, engine + VIA_REG_CR_TRANSPACE);
0442 break;
0443 default:
0444 writel(0x00FE0000, engine + VIA_REG_TRANSET);
0445 writel(0x080003FE, engine + VIA_REG_TRANSPACE);
0446 writel(0x0A00027C, engine + VIA_REG_TRANSPACE);
0447 writel(0x0B000260, engine + VIA_REG_TRANSPACE);
0448 writel(0x0C000274, engine + VIA_REG_TRANSPACE);
0449 writel(0x0D000264, engine + VIA_REG_TRANSPACE);
0450 writel(0x0E000000, engine + VIA_REG_TRANSPACE);
0451 writel(0x0F000020, engine + VIA_REG_TRANSPACE);
0452 writel(0x1000027E, engine + VIA_REG_TRANSPACE);
0453 writel(0x110002FE, engine + VIA_REG_TRANSPACE);
0454 writel(0x200F0060, engine + VIA_REG_TRANSPACE);
0455
0456 writel(0x00000006, engine + VIA_REG_TRANSPACE);
0457 writel(0x40008C0F, engine + VIA_REG_TRANSPACE);
0458 writel(0x44000000, engine + VIA_REG_TRANSPACE);
0459 writel(0x45080C04, engine + VIA_REG_TRANSPACE);
0460 writel(0x46800408, engine + VIA_REG_TRANSPACE);
0461
0462 writel(vq_high, engine + VIA_REG_TRANSPACE);
0463 writel(vq_start_low, engine + VIA_REG_TRANSPACE);
0464 writel(vq_end_low, engine + VIA_REG_TRANSPACE);
0465 writel(vq_len, engine + VIA_REG_TRANSPACE);
0466 break;
0467 }
0468
0469
0470 writel(viapar->shared->cursor_vram_addr, engine + VIA_REG_CURSOR_MODE);
0471 writel(0x0, engine + VIA_REG_CURSOR_POS);
0472 writel(0x0, engine + VIA_REG_CURSOR_ORG);
0473 writel(0x0, engine + VIA_REG_CURSOR_BG);
0474 writel(0x0, engine + VIA_REG_CURSOR_FG);
0475 return;
0476 }
0477
0478 void viafb_show_hw_cursor(struct fb_info *info, int Status)
0479 {
0480 struct viafb_par *viapar = info->par;
0481 u32 temp, iga_path = viapar->iga_path;
0482
0483 temp = readl(viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE);
0484 switch (Status) {
0485 case HW_Cursor_ON:
0486 temp |= 0x1;
0487 break;
0488 case HW_Cursor_OFF:
0489 temp &= 0xFFFFFFFE;
0490 break;
0491 }
0492 switch (iga_path) {
0493 case IGA2:
0494 temp |= 0x80000000;
0495 break;
0496 case IGA1:
0497 default:
0498 temp &= 0x7FFFFFFF;
0499 }
0500 writel(temp, viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE);
0501 }
0502
0503 void viafb_wait_engine_idle(struct fb_info *info)
0504 {
0505 struct viafb_par *viapar = info->par;
0506 int loop = 0;
0507 u32 mask;
0508 void __iomem *engine = viapar->shared->vdev->engine_mmio;
0509
0510 switch (viapar->shared->chip_info.twod_engine) {
0511 case VIA_2D_ENG_H5:
0512 case VIA_2D_ENG_M1:
0513 mask = VIA_CMD_RGTR_BUSY_M1 | VIA_2D_ENG_BUSY_M1 |
0514 VIA_3D_ENG_BUSY_M1;
0515 break;
0516 default:
0517 while (!(readl(engine + VIA_REG_STATUS) &
0518 VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) {
0519 loop++;
0520 cpu_relax();
0521 }
0522 mask = VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY;
0523 break;
0524 }
0525
0526 while ((readl(engine + VIA_REG_STATUS) & mask) && (loop < MAXLOOP)) {
0527 loop++;
0528 cpu_relax();
0529 }
0530
0531 if (loop >= MAXLOOP)
0532 printk(KERN_ERR "viafb_wait_engine_idle: not syncing\n");
0533 }