^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * linux/drivers/video/arkfb.c -- Frame buffer device driver for ARK 2000PV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * with ICS 5342 dac (it is easy to add support for different dacs).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2007 Ondrej Zajicek <santiago@crfreenet.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * License. See the file COPYING in the main directory of this archive for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Code is based on s3fb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/svga.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/console.h> /* Why should fb driver call console functions? because console_lock() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <video/vga.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct arkfb_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) int mclk_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) int wc_cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct dac_info *dac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct vgastate state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct mutex open_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) unsigned int ref_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) u32 pseudo_palette[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static const struct svga_fb_format arkfb_formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) { 0, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP4, FB_VISUAL_PSEUDOCOLOR, 8, 8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) { 4, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 8, 16},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) { 4, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) FB_TYPE_INTERLEAVED_PLANES, 1, FB_VISUAL_PSEUDOCOLOR, 8, 16},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) { 8, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 8, 8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {16, {10, 5, 0}, {5, 5, 0}, {0, 5, 0}, {0, 0, 0}, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_TRUECOLOR, 4, 4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {16, {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_TRUECOLOR, 4, 4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {24, {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_TRUECOLOR, 8, 8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {32, {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_TRUECOLOR, 2, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) SVGA_FORMAT_END
^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) /* CRT timing register sets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static const struct vga_regset ark_h_total_regs[] = {{0x00, 0, 7}, {0x41, 7, 7}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static const struct vga_regset ark_h_display_regs[] = {{0x01, 0, 7}, {0x41, 6, 6}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static const struct vga_regset ark_h_blank_start_regs[] = {{0x02, 0, 7}, {0x41, 5, 5}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static const struct vga_regset ark_h_blank_end_regs[] = {{0x03, 0, 4}, {0x05, 7, 7 }, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static const struct vga_regset ark_h_sync_start_regs[] = {{0x04, 0, 7}, {0x41, 4, 4}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static const struct vga_regset ark_h_sync_end_regs[] = {{0x05, 0, 4}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static const struct vga_regset ark_v_total_regs[] = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x40, 7, 7}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static const struct vga_regset ark_v_display_regs[] = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x40, 6, 6}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static const struct vga_regset ark_v_blank_start_regs[] = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x40, 5, 5}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) // const struct vga_regset ark_v_blank_end_regs[] = {{0x16, 0, 6}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static const struct vga_regset ark_v_blank_end_regs[] = {{0x16, 0, 7}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static const struct vga_regset ark_v_sync_start_regs[] = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x40, 4, 4}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static const struct vga_regset ark_v_sync_end_regs[] = {{0x11, 0, 3}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static const struct vga_regset ark_line_compare_regs[] = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static const struct vga_regset ark_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x40, 0, 2}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static const struct vga_regset ark_offset_regs[] = {{0x13, 0, 7}, {0x41, 3, 3}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static const struct svga_timing_regs ark_timing_regs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) ark_h_total_regs, ark_h_display_regs, ark_h_blank_start_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ark_h_blank_end_regs, ark_h_sync_start_regs, ark_h_sync_end_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) ark_v_total_regs, ark_v_display_regs, ark_v_blank_start_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) ark_v_blank_end_regs, ark_v_sync_start_regs, ark_v_sync_end_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^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) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* Module parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static char *mode_option = "640x480-8@60";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) MODULE_AUTHOR("(c) 2007 Ondrej Zajicek <santiago@crfreenet.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) MODULE_DESCRIPTION("fbdev driver for ARK 2000PV");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) module_param(mode_option, charp, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) module_param_named(mode, mode_option, charp, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) MODULE_PARM_DESC(mode, "Default video mode ('640x480-8@60', etc) (deprecated)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static int threshold = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) module_param(threshold, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) MODULE_PARM_DESC(threshold, "FIFO threshold");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static void arkfb_settile(struct fb_info *info, struct fb_tilemap *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) const u8 *font = map->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) u8 __iomem *fb = (u8 __iomem *)info->screen_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int i, c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if ((map->width != 8) || (map->height != 16) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) (map->depth != 1) || (map->length != 256)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) fb_err(info, "unsupported font parameters: width %d, height %d, depth %d, length %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) map->width, map->height, map->depth, map->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) fb += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) for (c = 0; c < map->length; c++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) for (i = 0; i < map->height; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) fb_writeb(font[i], &fb[i * 4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) fb_writeb(font[i], &fb[i * 4 + (128 * 8)]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) fb += 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if ((c % 8) == 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) fb += 128*8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) font += map->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static void arkfb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct arkfb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) svga_tilecursor(par->state.vgabase, info, cursor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static struct fb_tile_ops arkfb_tile_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .fb_settile = arkfb_settile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .fb_tilecopy = svga_tilecopy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .fb_tilefill = svga_tilefill,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .fb_tileblit = svga_tileblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .fb_tilecursor = arkfb_tilecursor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .fb_get_tilemax = svga_get_tilemax,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /* image data is MSB-first, fb structure is MSB-first too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static inline u32 expand_color(u32 c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return ((c & 1) | ((c & 2) << 7) | ((c & 4) << 14) | ((c & 8) << 21)) * 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* arkfb_iplan_imageblit silently assumes that almost everything is 8-pixel aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static void arkfb_iplan_imageblit(struct fb_info *info, const struct fb_image *image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) u32 fg = expand_color(image->fg_color);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) u32 bg = expand_color(image->bg_color);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) const u8 *src1, *src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) u8 __iomem *dst1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) u32 __iomem *dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) int x, y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) src1 = image->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) dst1 = info->screen_base + (image->dy * info->fix.line_length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) + ((image->dx / 8) * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) for (y = 0; y < image->height; y++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) src = src1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) dst = (u32 __iomem *) dst1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) for (x = 0; x < image->width; x += 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) val = *(src++) * 0x01010101;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) val = (val & fg) | (~val & bg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) fb_writel(val, dst++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) src1 += image->width / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) dst1 += info->fix.line_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /* arkfb_iplan_fillrect silently assumes that almost everything is 8-pixel aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static void arkfb_iplan_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) u32 fg = expand_color(rect->color);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) u8 __iomem *dst1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) u32 __iomem *dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) int x, y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) dst1 = info->screen_base + (rect->dy * info->fix.line_length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) + ((rect->dx / 8) * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) for (y = 0; y < rect->height; y++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) dst = (u32 __iomem *) dst1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) for (x = 0; x < rect->width; x += 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) fb_writel(fg, dst++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) dst1 += info->fix.line_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /* image data is MSB-first, fb structure is high-nibble-in-low-byte-first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static inline u32 expand_pixel(u32 c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return (((c & 1) << 24) | ((c & 2) << 27) | ((c & 4) << 14) | ((c & 8) << 17) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) ((c & 16) << 4) | ((c & 32) << 7) | ((c & 64) >> 6) | ((c & 128) >> 3)) * 0xF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* arkfb_cfb4_imageblit silently assumes that almost everything is 8-pixel aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static void arkfb_cfb4_imageblit(struct fb_info *info, const struct fb_image *image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) u32 fg = image->fg_color * 0x11111111;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) u32 bg = image->bg_color * 0x11111111;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) const u8 *src1, *src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) u8 __iomem *dst1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) u32 __iomem *dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) int x, y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) src1 = image->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) dst1 = info->screen_base + (image->dy * info->fix.line_length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) + ((image->dx / 8) * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) for (y = 0; y < image->height; y++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) src = src1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) dst = (u32 __iomem *) dst1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) for (x = 0; x < image->width; x += 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) val = expand_pixel(*(src++));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) val = (val & fg) | (~val & bg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) fb_writel(val, dst++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) src1 += image->width / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) dst1 += info->fix.line_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static void arkfb_imageblit(struct fb_info *info, const struct fb_image *image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if ((info->var.bits_per_pixel == 4) && (image->depth == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) && ((image->width % 8) == 0) && ((image->dx % 8) == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (info->fix.type == FB_TYPE_INTERLEAVED_PLANES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) arkfb_iplan_imageblit(info, image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) arkfb_cfb4_imageblit(info, image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) cfb_imageblit(info, image);
^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) static void arkfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if ((info->var.bits_per_pixel == 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) && ((rect->width % 8) == 0) && ((rect->dx % 8) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) && (info->fix.type == FB_TYPE_INTERLEAVED_PLANES))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) arkfb_iplan_fillrect(info, rect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) cfb_fillrect(info, rect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) enum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) DAC_PSEUDO8_8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) DAC_RGB1555_8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) DAC_RGB0565_8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) DAC_RGB0888_8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) DAC_RGB8888_8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) DAC_PSEUDO8_16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) DAC_RGB1555_16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) DAC_RGB0565_16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) DAC_RGB0888_16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) DAC_RGB8888_16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) DAC_MAX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) struct dac_ops {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) int (*dac_get_mode)(struct dac_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) int (*dac_set_mode)(struct dac_info *info, int mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) int (*dac_get_freq)(struct dac_info *info, int channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) int (*dac_set_freq)(struct dac_info *info, int channel, u32 freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) void (*dac_release)(struct dac_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) typedef void (*dac_read_regs_t)(void *data, u8 *code, int count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) typedef void (*dac_write_regs_t)(void *data, u8 *code, int count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct dac_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) struct dac_ops *dacops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) dac_read_regs_t dac_read_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) dac_write_regs_t dac_write_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static inline u8 dac_read_reg(struct dac_info *info, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) u8 code[2] = {reg, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) info->dac_read_regs(info->data, code, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return code[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) static inline void dac_read_regs(struct dac_info *info, u8 *code, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) info->dac_read_regs(info->data, code, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static inline void dac_write_reg(struct dac_info *info, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) u8 code[2] = {reg, val};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) info->dac_write_regs(info->data, code, 1);
^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) static inline void dac_write_regs(struct dac_info *info, u8 *code, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) info->dac_write_regs(info->data, code, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static inline int dac_set_mode(struct dac_info *info, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return info->dacops->dac_set_mode(info, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static inline int dac_set_freq(struct dac_info *info, int channel, u32 freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return info->dacops->dac_set_freq(info, channel, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) static inline void dac_release(struct dac_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) info->dacops->dac_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* ICS5342 DAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) struct ics5342_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct dac_info dac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) u8 mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) #define DAC_PAR(info) ((struct ics5342_info *) info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /* LSB is set to distinguish unused slots */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static const u8 ics5342_mode_table[DAC_MAX] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) [DAC_PSEUDO8_8] = 0x01, [DAC_RGB1555_8] = 0x21, [DAC_RGB0565_8] = 0x61,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) [DAC_RGB0888_8] = 0x41, [DAC_PSEUDO8_16] = 0x11, [DAC_RGB1555_16] = 0x31,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) [DAC_RGB0565_16] = 0x51, [DAC_RGB0888_16] = 0x91, [DAC_RGB8888_16] = 0x71
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static int ics5342_set_mode(struct dac_info *info, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) u8 code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (mode >= DAC_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) code = ics5342_mode_table[mode];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (! code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) dac_write_reg(info, 6, code & 0xF0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) DAC_PAR(info)->mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static const struct svga_pll ics5342_pll = {3, 129, 3, 33, 0, 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 60000, 250000, 14318};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /* pd4 - allow only posdivider 4 (r=2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) static const struct svga_pll ics5342_pll_pd4 = {3, 129, 3, 33, 2, 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 60000, 335000, 14318};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* 270 MHz should be upper bound for VCO clock according to specs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) but that is too restrictive in pd4 case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static int ics5342_set_freq(struct dac_info *info, int channel, u32 freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) u16 m, n, r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) /* only postdivider 4 (r=2) is valid in mode DAC_PSEUDO8_16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) int rv = svga_compute_pll((DAC_PAR(info)->mode == DAC_PSEUDO8_16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) ? &ics5342_pll_pd4 : &ics5342_pll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) freq, &m, &n, &r, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (rv < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) u8 code[6] = {4, 3, 5, m-2, 5, (n-2) | (r << 5)};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) dac_write_regs(info, code, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) static void ics5342_release(struct dac_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) ics5342_set_mode(info, DAC_PSEUDO8_8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) kfree(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) static struct dac_ops ics5342_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) .dac_set_mode = ics5342_set_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) .dac_set_freq = ics5342_set_freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) .dac_release = ics5342_release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static struct dac_info * ics5342_init(dac_read_regs_t drr, dac_write_regs_t dwr, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) struct dac_info *info = kzalloc(sizeof(struct ics5342_info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (! info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) info->dacops = &ics5342_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) info->dac_read_regs = drr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) info->dac_write_regs = dwr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) info->data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) DAC_PAR(info)->mode = DAC_PSEUDO8_8; /* estimation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) return info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) static unsigned short dac_regs[4] = {0x3c8, 0x3c9, 0x3c6, 0x3c7};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static void ark_dac_read_regs(void *data, u8 *code, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) struct fb_info *info = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) struct arkfb_info *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) u8 regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) regval = vga_rseq(par->state.vgabase, 0x1C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) while (count != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) vga_wseq(par->state.vgabase, 0x1C, regval | (code[0] & 4 ? 0x80 : 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) code[1] = vga_r(par->state.vgabase, dac_regs[code[0] & 3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) code += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) vga_wseq(par->state.vgabase, 0x1C, regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) static void ark_dac_write_regs(void *data, u8 *code, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct fb_info *info = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) struct arkfb_info *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) u8 regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) regval = vga_rseq(par->state.vgabase, 0x1C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) while (count != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) vga_wseq(par->state.vgabase, 0x1C, regval | (code[0] & 4 ? 0x80 : 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) vga_w(par->state.vgabase, dac_regs[code[0] & 3], code[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) code += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) vga_wseq(par->state.vgabase, 0x1C, regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) static void ark_set_pixclock(struct fb_info *info, u32 pixclock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) struct arkfb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) u8 regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) int rv = dac_set_freq(par->dac, 0, 1000000000 / pixclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (rv < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) fb_err(info, "cannot set requested pixclock, keeping old value\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /* Set VGA misc register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) regval = vga_r(par->state.vgabase, VGA_MIS_R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) /* Open framebuffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) static int arkfb_open(struct fb_info *info, int user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) struct arkfb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) mutex_lock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (par->ref_count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) void __iomem *vgabase = par->state.vgabase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) memset(&(par->state), 0, sizeof(struct vgastate));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) par->state.vgabase = vgabase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) par->state.num_crtc = 0x60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) par->state.num_seq = 0x30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) save_vga(&(par->state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) par->ref_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) /* Close framebuffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) static int arkfb_release(struct fb_info *info, int user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct arkfb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) mutex_lock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (par->ref_count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (par->ref_count == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) restore_vga(&(par->state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) dac_set_mode(par->dac, DAC_PSEUDO8_8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) par->ref_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) /* Validate passed in var */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) static int arkfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) int rv, mem, step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /* Find appropriate format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) rv = svga_match_format (arkfb_formats, var, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (rv < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) fb_err(info, "unsupported mode requested\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) /* Do not allow to have real resoulution larger than virtual */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (var->xres > var->xres_virtual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) var->xres_virtual = var->xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (var->yres > var->yres_virtual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) var->yres_virtual = var->yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) /* Round up xres_virtual to have proper alignment of lines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) step = arkfb_formats[rv].xresstep - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) var->xres_virtual = (var->xres_virtual+step) & ~step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /* Check whether have enough memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (mem > info->screen_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) fb_err(info, "not enough framebuffer memory (%d kB requested, %d kB available)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) mem >> 10, (unsigned int) (info->screen_size >> 10));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) rv = svga_check_timings (&ark_timing_regs, var, info->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (rv < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) fb_err(info, "invalid timings requested\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /* Interlaced mode is broken */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (var->vmode & FB_VMODE_INTERLACED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /* Set video mode from par */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) static int arkfb_set_par(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) struct arkfb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) u32 value, mode, hmul, hdiv, offset_value, screen_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) u32 bpp = info->var.bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) u8 regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (bpp != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) info->fix.ypanstep = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) info->fix.line_length = (info->var.xres_virtual * bpp) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) info->flags &= ~FBINFO_MISC_TILEBLITTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) info->tileops = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) /* in 4bpp supports 8p wide tiles only, any tiles otherwise */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) info->pixmap.blit_y = ~(u32)0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) offset_value = (info->var.xres_virtual * bpp) / 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) screen_size = info->var.yres_virtual * info->fix.line_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) info->fix.ypanstep = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) info->fix.line_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) info->flags |= FBINFO_MISC_TILEBLITTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) info->tileops = &arkfb_tile_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) /* supports 8x16 tiles only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) info->pixmap.blit_x = 1 << (8 - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) info->pixmap.blit_y = 1 << (16 - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) offset_value = info->var.xres_virtual / 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) info->var.xoffset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) info->var.yoffset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) info->var.activate = FB_ACTIVATE_NOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) /* Unlock registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /* Blank screen and turn off sync */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) /* Set default values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) svga_set_default_gfx_regs(par->state.vgabase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) svga_set_default_atc_regs(par->state.vgabase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) svga_set_default_seq_regs(par->state.vgabase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) svga_set_default_crt_regs(par->state.vgabase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) svga_wcrt_multi(par->state.vgabase, ark_line_compare_regs, 0xFFFFFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) svga_wcrt_multi(par->state.vgabase, ark_start_address_regs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) /* ARK specific initialization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) svga_wseq_mask(par->state.vgabase, 0x10, 0x1F, 0x1F); /* enable linear framebuffer and full memory access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) svga_wseq_mask(par->state.vgabase, 0x12, 0x03, 0x03); /* 4 MB linear framebuffer size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) vga_wseq(par->state.vgabase, 0x13, info->fix.smem_start >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) vga_wseq(par->state.vgabase, 0x14, info->fix.smem_start >> 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) vga_wseq(par->state.vgabase, 0x15, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) vga_wseq(par->state.vgabase, 0x16, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) /* Set the FIFO threshold register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /* It is fascinating way to store 5-bit value in 8-bit register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) regval = 0x10 | ((threshold & 0x0E) >> 1) | (threshold & 0x01) << 7 | (threshold & 0x10) << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) vga_wseq(par->state.vgabase, 0x18, regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) /* Set the offset register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) fb_dbg(info, "offset register : %d\n", offset_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) svga_wcrt_multi(par->state.vgabase, ark_offset_regs, offset_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) /* fix for hi-res textmode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) svga_wcrt_mask(par->state.vgabase, 0x40, 0x08, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (info->var.vmode & FB_VMODE_DOUBLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (info->var.vmode & FB_VMODE_INTERLACED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) svga_wcrt_mask(par->state.vgabase, 0x44, 0x04, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) svga_wcrt_mask(par->state.vgabase, 0x44, 0x00, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) hmul = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) hdiv = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) mode = svga_match_format(arkfb_formats, &(info->var), &(info->fix));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) /* Set mode-specific register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) fb_dbg(info, "text mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) svga_set_textmode_vga_regs(par->state.vgabase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) dac_set_mode(par->dac, DAC_PSEUDO8_8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) fb_dbg(info, "4 bit pseudocolor\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) dac_set_mode(par->dac, DAC_PSEUDO8_8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) fb_dbg(info, "4 bit pseudocolor, planar\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) vga_wseq(par->state.vgabase, 0x11, 0x10); /* basic VGA mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) dac_set_mode(par->dac, DAC_PSEUDO8_8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) fb_dbg(info, "8 bit pseudocolor\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) vga_wseq(par->state.vgabase, 0x11, 0x16); /* 8bpp accel mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (info->var.pixclock > 20000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) fb_dbg(info, "not using multiplex\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) svga_wcrt_mask(par->state.vgabase, 0x46, 0x00, 0x04); /* 8bit pixel path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) dac_set_mode(par->dac, DAC_PSEUDO8_8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) fb_dbg(info, "using multiplex\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) dac_set_mode(par->dac, DAC_PSEUDO8_16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) hdiv = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) fb_dbg(info, "5/5/5 truecolor\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) vga_wseq(par->state.vgabase, 0x11, 0x1A); /* 16bpp accel mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) dac_set_mode(par->dac, DAC_RGB1555_16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) fb_dbg(info, "5/6/5 truecolor\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) vga_wseq(par->state.vgabase, 0x11, 0x1A); /* 16bpp accel mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) dac_set_mode(par->dac, DAC_RGB0565_16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) fb_dbg(info, "8/8/8 truecolor\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) vga_wseq(par->state.vgabase, 0x11, 0x16); /* 8bpp accel mode ??? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) dac_set_mode(par->dac, DAC_RGB0888_16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) hmul = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) hdiv = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) fb_dbg(info, "8/8/8/8 truecolor\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) vga_wseq(par->state.vgabase, 0x11, 0x1E); /* 32bpp accel mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) svga_wcrt_mask(par->state.vgabase, 0x46, 0x04, 0x04); /* 16bit pixel path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) dac_set_mode(par->dac, DAC_RGB8888_16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) hmul = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) fb_err(info, "unsupported mode - bug\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) ark_set_pixclock(info, (hdiv * info->var.pixclock) / hmul);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) svga_set_timings(par->state.vgabase, &ark_timing_regs, &(info->var), hmul, hdiv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) hmul, info->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /* Set interlaced mode start/end register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) value = ((value * hmul / hdiv) / 8) - 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) vga_wcrt(par->state.vgabase, 0x42, (value + 1) / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) memset_io(info->screen_base, 0x00, screen_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) /* Device and screen back on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) /* Set a colour register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) static int arkfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) u_int transp, struct fb_info *fb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) switch (fb->var.bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (regno >= 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if ((fb->var.bits_per_pixel == 4) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) (fb->var.nonstd == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) outb(0xF0, VGA_PEL_MSK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) outb(regno*16, VGA_PEL_IW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) outb(0x0F, VGA_PEL_MSK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) outb(regno, VGA_PEL_IW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) outb(red >> 10, VGA_PEL_D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) outb(green >> 10, VGA_PEL_D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) outb(blue >> 10, VGA_PEL_D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) if (regno >= 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) outb(0xFF, VGA_PEL_MSK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) outb(regno, VGA_PEL_IW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) outb(red >> 10, VGA_PEL_D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) outb(green >> 10, VGA_PEL_D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) outb(blue >> 10, VGA_PEL_D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (regno >= 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (fb->var.green.length == 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) ((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) ((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) else if (fb->var.green.length == 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) ((u32*)fb->pseudo_palette)[regno] = (red & 0xF800) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (regno >= 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) ((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) (green & 0xFF00) | ((blue & 0xFF00) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) /* Set the display blanking state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) static int arkfb_blank(int blank_mode, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) struct arkfb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) switch (blank_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) case FB_BLANK_UNBLANK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) fb_dbg(info, "unblank\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) case FB_BLANK_NORMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) fb_dbg(info, "blank\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) case FB_BLANK_POWERDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) case FB_BLANK_HSYNC_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) case FB_BLANK_VSYNC_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) fb_dbg(info, "sync down\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) /* Pan the display */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) struct arkfb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) unsigned int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) /* Calculate the offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (info->var.bits_per_pixel == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) offset = (var->yoffset / 16) * (info->var.xres_virtual / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) + (var->xoffset / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) offset = offset >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) offset = (var->yoffset * info->fix.line_length) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) (var->xoffset * info->var.bits_per_pixel / 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) /* Set the offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) svga_wcrt_multi(par->state.vgabase, ark_start_address_regs, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) /* Frame buffer operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) static const struct fb_ops arkfb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) .fb_open = arkfb_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) .fb_release = arkfb_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) .fb_check_var = arkfb_check_var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) .fb_set_par = arkfb_set_par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) .fb_setcolreg = arkfb_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) .fb_blank = arkfb_blank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) .fb_pan_display = arkfb_pan_display,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) .fb_fillrect = arkfb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) .fb_copyarea = cfb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) .fb_imageblit = arkfb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) .fb_get_caps = svga_get_caps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /* PCI probe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) static int ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct pci_bus_region bus_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct resource vga_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) struct arkfb_info *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) u8 regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) /* Ignore secondary VGA device because there is no VGA arbitration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (! svga_primary_device(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) dev_info(&(dev->dev), "ignoring secondary device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) /* Allocate and fill driver data structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) info = framebuffer_alloc(sizeof(struct arkfb_info), &(dev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) mutex_init(&par->open_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) info->flags = FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) info->fbops = &arkfb_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) /* Prepare PCI device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) rc = pci_enable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) dev_err(info->device, "cannot enable PCI device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) goto err_enable_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) rc = pci_request_regions(dev, "arkfb");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) dev_err(info->device, "cannot reserve framebuffer region\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) goto err_request_regions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) par->dac = ics5342_init(ark_dac_read_regs, ark_dac_write_regs, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) if (! par->dac) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) dev_err(info->device, "RAMDAC initialization failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) goto err_dac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) info->fix.smem_start = pci_resource_start(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) info->fix.smem_len = pci_resource_len(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) /* Map physical IO memory address into kernel space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) info->screen_base = pci_iomap_wc(dev, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (! info->screen_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) dev_err(info->device, "iomap for framebuffer failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) goto err_iomap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) bus_reg.start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) bus_reg.end = 64 * 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) vga_res.flags = IORESOURCE_IO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) pcibios_bus_to_resource(dev->bus, &vga_res, &bus_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) par->state.vgabase = (void __iomem *) (unsigned long) vga_res.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) /* FIXME get memsize */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) regval = vga_rseq(par->state.vgabase, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) info->screen_size = (1 << (regval >> 6)) << 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) info->fix.smem_len = info->screen_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) strcpy(info->fix.id, "ARK 2000PV");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) info->fix.mmio_start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) info->fix.mmio_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) info->fix.type = FB_TYPE_PACKED_PIXELS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) info->fix.ypanstep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) info->fix.accel = FB_ACCEL_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) info->pseudo_palette = (void*) (par->pseudo_palette);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) /* Prepare startup mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (! ((rc == 1) || (rc == 2))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) dev_err(info->device, "mode %s not found\n", mode_option);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) goto err_find_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) rc = fb_alloc_cmap(&info->cmap, 256, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) dev_err(info->device, "cannot allocate colormap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) goto err_alloc_cmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) rc = register_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) dev_err(info->device, "cannot register framebuffer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) goto err_reg_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) fb_info(info, "%s on %s, %d MB RAM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) info->fix.id, pci_name(dev), info->fix.smem_len >> 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) /* Record a reference to the driver data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) pci_set_drvdata(dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) par->wc_cookie = arch_phys_wc_add(info->fix.smem_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) info->fix.smem_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) /* Error handling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) err_reg_fb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) err_alloc_cmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) err_find_mode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) pci_iounmap(dev, info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) err_iomap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) dac_release(par->dac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) err_dac:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) pci_release_regions(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) err_request_regions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) /* pci_disable_device(dev); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) err_enable_device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) /* PCI remove */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) static void ark_pci_remove(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) struct fb_info *info = pci_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) struct arkfb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) arch_phys_wc_del(par->wc_cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) dac_release(par->dac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) unregister_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) pci_iounmap(dev, info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) pci_release_regions(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) /* pci_disable_device(dev); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) /* PCI suspend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) static int __maybe_unused ark_pci_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) struct fb_info *info = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) struct arkfb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) dev_info(info->device, "suspend\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) mutex_lock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) if (par->ref_count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) fb_set_suspend(info, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) /* PCI resume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) static int __maybe_unused ark_pci_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) struct fb_info *info = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) struct arkfb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) dev_info(info->device, "resume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) mutex_lock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if (par->ref_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) arkfb_set_par(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) fb_set_suspend(info, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) static const struct dev_pm_ops ark_pci_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) .suspend = ark_pci_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) .resume = ark_pci_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) .freeze = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) .thaw = ark_pci_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) .poweroff = ark_pci_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) .restore = ark_pci_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) /* List of boards that we are trying to support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) static const struct pci_device_id ark_devices[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) {PCI_DEVICE(0xEDD8, 0xA099)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) {0, 0, 0, 0, 0, 0, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) MODULE_DEVICE_TABLE(pci, ark_devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) static struct pci_driver arkfb_pci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) .name = "arkfb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) .id_table = ark_devices,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) .probe = ark_pci_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) .remove = ark_pci_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) .driver.pm = &ark_pci_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) /* Cleanup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) static void __exit arkfb_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) pr_debug("arkfb: cleaning up\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) pci_unregister_driver(&arkfb_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) /* Driver Initialisation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) static int __init arkfb_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) char *option = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (fb_get_options("arkfb", &option))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) if (option && *option)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) mode_option = option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) pr_debug("arkfb: initializing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) return pci_register_driver(&arkfb_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) module_init(arkfb_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) module_exit(arkfb_cleanup);