^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * linux/drivers/video/vt8623fb.c - fbdev driver for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * integrated graphic core in VIA VT8623 [CLE266] chipset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2006-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, some parts are from David Boucher's viafb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * (http://davesdomain.org.uk/viafb/)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/tty.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 vt8623fb_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) char __iomem *mmio_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) int wc_cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct vgastate state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct mutex open_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) unsigned int ref_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) u32 pseudo_palette[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^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) static const struct svga_fb_format vt8623fb_formats[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) { 0, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP8, FB_VISUAL_PSEUDOCOLOR, 16, 16},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) { 4, {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_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 16, 16},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) { 4, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) FB_TYPE_INTERLEAVED_PLANES, 1, FB_VISUAL_PSEUDOCOLOR, 16, 16},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) { 8, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 8, 8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* {16, {10, 5, 0}, {5, 5, 0}, {0, 5, 0}, {0, 0, 0}, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_TRUECOLOR, 4, 4}, */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {16, {11, 5, 0}, {5, 6, 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) {32, {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_TRUECOLOR, 2, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) SVGA_FORMAT_END
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static const struct svga_pll vt8623_pll = {2, 127, 2, 7, 0, 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) 60000, 300000, 14318};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* CRT timing register sets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static const struct vga_regset vt8623_h_total_regs[] = {{0x00, 0, 7}, {0x36, 3, 3}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static const struct vga_regset vt8623_h_display_regs[] = {{0x01, 0, 7}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static const struct vga_regset vt8623_h_blank_start_regs[] = {{0x02, 0, 7}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static const struct vga_regset vt8623_h_blank_end_regs[] = {{0x03, 0, 4}, {0x05, 7, 7}, {0x33, 5, 5}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static const struct vga_regset vt8623_h_sync_start_regs[] = {{0x04, 0, 7}, {0x33, 4, 4}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static const struct vga_regset vt8623_h_sync_end_regs[] = {{0x05, 0, 4}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static const struct vga_regset vt8623_v_total_regs[] = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x35, 0, 0}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static const struct vga_regset vt8623_v_display_regs[] = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x35, 2, 2}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static const struct vga_regset vt8623_v_blank_start_regs[] = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x35, 3, 3}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static const struct vga_regset vt8623_v_blank_end_regs[] = {{0x16, 0, 7}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static const struct vga_regset vt8623_v_sync_start_regs[] = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x35, 1, 1}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static const struct vga_regset vt8623_v_sync_end_regs[] = {{0x11, 0, 3}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static const struct vga_regset vt8623_offset_regs[] = {{0x13, 0, 7}, {0x35, 5, 7}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static const struct vga_regset vt8623_line_compare_regs[] = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x33, 0, 2}, {0x35, 4, 4}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static const struct vga_regset vt8623_fetch_count_regs[] = {{0x1C, 0, 7}, {0x1D, 0, 1}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static const struct vga_regset vt8623_start_address_regs[] = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x34, 0, 7}, {0x48, 0, 1}, VGA_REGSET_END};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static const struct svga_timing_regs vt8623_timing_regs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) vt8623_h_total_regs, vt8623_h_display_regs, vt8623_h_blank_start_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) vt8623_h_blank_end_regs, vt8623_h_sync_start_regs, vt8623_h_sync_end_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) vt8623_v_total_regs, vt8623_v_display_regs, vt8623_v_blank_start_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) vt8623_v_blank_end_regs, vt8623_v_sync_start_regs, vt8623_v_sync_end_regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^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) /* Module parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static char *mode_option = "640x480-8@60";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static int mtrr = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) MODULE_AUTHOR("(c) 2006 Ondrej Zajicek <santiago@crfreenet.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) MODULE_DESCRIPTION("fbdev driver for integrated graphics core in VIA VT8623 [CLE266]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) module_param(mode_option, charp, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) module_param_named(mode, mode_option, charp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) MODULE_PARM_DESC(mode, "Default video mode e.g. '648x480-8@60' (deprecated)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) module_param(mtrr, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static void vt8623fb_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct vt8623fb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) svga_tilecursor(par->state.vgabase, info, cursor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static struct fb_tile_ops vt8623fb_tile_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .fb_settile = svga_settile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .fb_tilecopy = svga_tilecopy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .fb_tilefill = svga_tilefill,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .fb_tileblit = svga_tileblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .fb_tilecursor = vt8623fb_tilecursor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .fb_get_tilemax = svga_get_tilemax,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /* image data is MSB-first, fb structure is MSB-first too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static inline u32 expand_color(u32 c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return ((c & 1) | ((c & 2) << 7) | ((c & 4) << 14) | ((c & 8) << 21)) * 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* vt8623fb_iplan_imageblit silently assumes that almost everything is 8-pixel aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static void vt8623fb_iplan_imageblit(struct fb_info *info, const struct fb_image *image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) u32 fg = expand_color(image->fg_color);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) u32 bg = expand_color(image->bg_color);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) const u8 *src1, *src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) u8 __iomem *dst1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) u32 __iomem *dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) int x, y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) src1 = image->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) dst1 = info->screen_base + (image->dy * info->fix.line_length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) + ((image->dx / 8) * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) for (y = 0; y < image->height; y++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) src = src1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) dst = (u32 __iomem *) dst1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) for (x = 0; x < image->width; x += 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) val = *(src++) * 0x01010101;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) val = (val & fg) | (~val & bg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) fb_writel(val, dst++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) src1 += image->width / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) dst1 += info->fix.line_length;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /* vt8623fb_iplan_fillrect silently assumes that almost everything is 8-pixel aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static void vt8623fb_iplan_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) u32 fg = expand_color(rect->color);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) u8 __iomem *dst1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) u32 __iomem *dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) int x, y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) dst1 = info->screen_base + (rect->dy * info->fix.line_length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) + ((rect->dx / 8) * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) for (y = 0; y < rect->height; y++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) dst = (u32 __iomem *) dst1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) for (x = 0; x < rect->width; x += 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) fb_writel(fg, dst++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) dst1 += info->fix.line_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /* image data is MSB-first, fb structure is high-nibble-in-low-byte-first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static inline u32 expand_pixel(u32 c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return (((c & 1) << 24) | ((c & 2) << 27) | ((c & 4) << 14) | ((c & 8) << 17) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) ((c & 16) << 4) | ((c & 32) << 7) | ((c & 64) >> 6) | ((c & 128) >> 3)) * 0xF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /* vt8623fb_cfb4_imageblit silently assumes that almost everything is 8-pixel aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static void vt8623fb_cfb4_imageblit(struct fb_info *info, const struct fb_image *image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) u32 fg = image->fg_color * 0x11111111;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) u32 bg = image->bg_color * 0x11111111;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) const u8 *src1, *src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) u8 __iomem *dst1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) u32 __iomem *dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) int x, y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) src1 = image->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) dst1 = info->screen_base + (image->dy * info->fix.line_length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) + ((image->dx / 8) * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) for (y = 0; y < image->height; y++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) src = src1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) dst = (u32 __iomem *) dst1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) for (x = 0; x < image->width; x += 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) val = expand_pixel(*(src++));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) val = (val & fg) | (~val & bg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) fb_writel(val, dst++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) src1 += image->width / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) dst1 += info->fix.line_length;
^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) static void vt8623fb_imageblit(struct fb_info *info, const struct fb_image *image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if ((info->var.bits_per_pixel == 4) && (image->depth == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) && ((image->width % 8) == 0) && ((image->dx % 8) == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (info->fix.type == FB_TYPE_INTERLEAVED_PLANES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) vt8623fb_iplan_imageblit(info, image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) vt8623fb_cfb4_imageblit(info, image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) cfb_imageblit(info, image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static void vt8623fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if ((info->var.bits_per_pixel == 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) && ((rect->width % 8) == 0) && ((rect->dx % 8) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) && (info->fix.type == FB_TYPE_INTERLEAVED_PLANES))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) vt8623fb_iplan_fillrect(info, rect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) cfb_fillrect(info, rect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static void vt8623_set_pixclock(struct fb_info *info, u32 pixclock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct vt8623fb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) u16 m, n, r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) u8 regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) rv = svga_compute_pll(&vt8623_pll, 1000000000 / pixclock, &m, &n, &r, info->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (rv < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) fb_err(info, "cannot set requested pixclock, keeping old value\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* Set VGA misc register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) regval = vga_r(par->state.vgabase, VGA_MIS_R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /* Set clock registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) vga_wseq(par->state.vgabase, 0x46, (n | (r << 6)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) vga_wseq(par->state.vgabase, 0x47, m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* PLL reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) svga_wseq_mask(par->state.vgabase, 0x40, 0x02, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) svga_wseq_mask(par->state.vgabase, 0x40, 0x00, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static int vt8623fb_open(struct fb_info *info, int user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct vt8623fb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) mutex_lock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (par->ref_count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) void __iomem *vgabase = par->state.vgabase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) memset(&(par->state), 0, sizeof(struct vgastate));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) par->state.vgabase = vgabase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) par->state.num_crtc = 0xA2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) par->state.num_seq = 0x50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) save_vga(&(par->state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) par->ref_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return 0;
^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) static int vt8623fb_release(struct fb_info *info, int user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct vt8623fb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) mutex_lock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (par->ref_count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (par->ref_count == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) restore_vga(&(par->state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) par->ref_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return 0;
^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) static int vt8623fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) int rv, mem, step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) /* Find appropriate format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) rv = svga_match_format (vt8623fb_formats, var, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (rv < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) fb_err(info, "unsupported mode requested\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /* Do not allow to have real resoulution larger than virtual */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (var->xres > var->xres_virtual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) var->xres_virtual = var->xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (var->yres > var->yres_virtual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) var->yres_virtual = var->yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /* Round up xres_virtual to have proper alignment of lines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) step = vt8623fb_formats[rv].xresstep - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) var->xres_virtual = (var->xres_virtual+step) & ~step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) /* Check whether have enough memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (mem > info->screen_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) fb_err(info, "not enough framebuffer memory (%d kB requested, %d kB available)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) mem >> 10, (unsigned int) (info->screen_size >> 10));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /* Text mode is limited to 256 kB of memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if ((var->bits_per_pixel == 0) && (mem > (256*1024)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) fb_err(info, "text framebuffer size too large (%d kB requested, 256 kB possible)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) mem >> 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return -EINVAL;
^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) rv = svga_check_timings (&vt8623_timing_regs, var, info->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (rv < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) fb_err(info, "invalid timings requested\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /* Interlaced mode not supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (var->vmode & FB_VMODE_INTERLACED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static int vt8623fb_set_par(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) u32 mode, offset_value, fetch_value, screen_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) struct vt8623fb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) u32 bpp = info->var.bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (bpp != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) info->fix.ypanstep = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) info->fix.line_length = (info->var.xres_virtual * bpp) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) info->flags &= ~FBINFO_MISC_TILEBLITTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) info->tileops = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /* in 4bpp supports 8p wide tiles only, any tiles otherwise */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) info->pixmap.blit_y = ~(u32)0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) offset_value = (info->var.xres_virtual * bpp) / 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) fetch_value = ((info->var.xres * bpp) / 128) + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (bpp == 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) fetch_value = (info->var.xres / 8) + 8; /* + 0 is OK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) screen_size = info->var.yres_virtual * info->fix.line_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) info->fix.ypanstep = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) info->fix.line_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) info->flags |= FBINFO_MISC_TILEBLITTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) info->tileops = &vt8623fb_tile_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /* supports 8x16 tiles only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) info->pixmap.blit_x = 1 << (8 - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) info->pixmap.blit_y = 1 << (16 - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) offset_value = info->var.xres_virtual / 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) fetch_value = (info->var.xres / 8) + 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) info->var.xoffset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) info->var.yoffset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) info->var.activate = FB_ACTIVATE_NOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) /* Unlock registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) svga_wseq_mask(par->state.vgabase, 0x10, 0x01, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) svga_wcrt_mask(par->state.vgabase, 0x47, 0x00, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /* Device, screen and sync off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) svga_wcrt_mask(par->state.vgabase, 0x36, 0x30, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) svga_wcrt_mask(par->state.vgabase, 0x17, 0x00, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /* Set default values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) svga_set_default_gfx_regs(par->state.vgabase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) svga_set_default_atc_regs(par->state.vgabase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) svga_set_default_seq_regs(par->state.vgabase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) svga_set_default_crt_regs(par->state.vgabase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) svga_wcrt_multi(par->state.vgabase, vt8623_line_compare_regs, 0xFFFFFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) svga_wcrt_multi(par->state.vgabase, vt8623_start_address_regs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) svga_wcrt_multi(par->state.vgabase, vt8623_offset_regs, offset_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) svga_wseq_multi(par->state.vgabase, vt8623_fetch_count_regs, fetch_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) /* Clear H/V Skew */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) svga_wcrt_mask(par->state.vgabase, 0x03, 0x00, 0x60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) svga_wcrt_mask(par->state.vgabase, 0x05, 0x00, 0x60);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (info->var.vmode & FB_VMODE_DOUBLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) svga_wcrt_mask(par->state.vgabase, 0x09, 0x80, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) svga_wcrt_mask(par->state.vgabase, 0x09, 0x00, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) svga_wseq_mask(par->state.vgabase, 0x1E, 0xF0, 0xF0); // DI/DVP bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) svga_wseq_mask(par->state.vgabase, 0x2A, 0x0F, 0x0F); // DI/DVP bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) svga_wseq_mask(par->state.vgabase, 0x16, 0x08, 0xBF); // FIFO read threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) vga_wseq(par->state.vgabase, 0x17, 0x1F); // FIFO depth
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) vga_wseq(par->state.vgabase, 0x18, 0x4E);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) svga_wseq_mask(par->state.vgabase, 0x1A, 0x08, 0x08); // enable MMIO ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) vga_wcrt(par->state.vgabase, 0x32, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) vga_wcrt(par->state.vgabase, 0x34, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) vga_wcrt(par->state.vgabase, 0x6A, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) vga_wcrt(par->state.vgabase, 0x6A, 0xC0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) vga_wgfx(par->state.vgabase, 0x20, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) vga_wgfx(par->state.vgabase, 0x21, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) vga_wgfx(par->state.vgabase, 0x22, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) /* Set SR15 according to number of bits per pixel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) mode = svga_match_format(vt8623fb_formats, &(info->var), &(info->fix));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) fb_dbg(info, "text mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) svga_set_textmode_vga_regs(par->state.vgabase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) svga_wseq_mask(par->state.vgabase, 0x15, 0x00, 0xFE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) svga_wcrt_mask(par->state.vgabase, 0x11, 0x60, 0x70);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) fb_dbg(info, "4 bit pseudocolor\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) vga_wgfx(par->state.vgabase, VGA_GFX_MODE, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) svga_wseq_mask(par->state.vgabase, 0x15, 0x20, 0xFE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x70);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) fb_dbg(info, "4 bit pseudocolor, planar\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) svga_wseq_mask(par->state.vgabase, 0x15, 0x00, 0xFE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) svga_wcrt_mask(par->state.vgabase, 0x11, 0x00, 0x70);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) fb_dbg(info, "8 bit pseudocolor\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) svga_wseq_mask(par->state.vgabase, 0x15, 0x22, 0xFE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) fb_dbg(info, "5/6/5 truecolor\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) svga_wseq_mask(par->state.vgabase, 0x15, 0xB6, 0xFE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) fb_dbg(info, "8/8/8 truecolor\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) svga_wseq_mask(par->state.vgabase, 0x15, 0xAE, 0xFE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) printk(KERN_ERR "vt8623fb: unsupported mode - bug\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return (-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) vt8623_set_pixclock(info, info->var.pixclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) svga_set_timings(par->state.vgabase, &vt8623_timing_regs, &(info->var), 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) (info->var.vmode & FB_VMODE_DOUBLE) ? 2 : 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 1, info->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) memset_io(info->screen_base, 0x00, screen_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) /* Device and screen back on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) svga_wcrt_mask(par->state.vgabase, 0x17, 0x80, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) static int vt8623fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) u_int transp, struct fb_info *fb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) switch (fb->var.bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (regno >= 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) outb(0x0F, VGA_PEL_MSK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) outb(regno, VGA_PEL_IW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) outb(red >> 10, VGA_PEL_D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) outb(green >> 10, VGA_PEL_D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) outb(blue >> 10, VGA_PEL_D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (regno >= 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) outb(0xFF, VGA_PEL_MSK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) outb(regno, VGA_PEL_IW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) outb(red >> 10, VGA_PEL_D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) outb(green >> 10, VGA_PEL_D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) outb(blue >> 10, VGA_PEL_D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (regno >= 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (fb->var.green.length == 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) ((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) ((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) else if (fb->var.green.length == 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) ((u32*)fb->pseudo_palette)[regno] = (red & 0xF800) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (regno >= 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) /* ((transp & 0xFF00) << 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) ((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) (green & 0xFF00) | ((blue & 0xFF00) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) static int vt8623fb_blank(int blank_mode, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) struct vt8623fb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) switch (blank_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) case FB_BLANK_UNBLANK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) fb_dbg(info, "unblank\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) svga_wseq_mask(par->state.vgabase, 0x01, 0x00, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) case FB_BLANK_NORMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) fb_dbg(info, "blank\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) svga_wcrt_mask(par->state.vgabase, 0x36, 0x00, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) case FB_BLANK_HSYNC_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) fb_dbg(info, "DPMS standby (hsync off)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) svga_wcrt_mask(par->state.vgabase, 0x36, 0x10, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) case FB_BLANK_VSYNC_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) fb_dbg(info, "DPMS suspend (vsync off)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) svga_wcrt_mask(par->state.vgabase, 0x36, 0x20, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) case FB_BLANK_POWERDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) fb_dbg(info, "DPMS off (no sync)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) svga_wcrt_mask(par->state.vgabase, 0x36, 0x30, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) svga_wseq_mask(par->state.vgabase, 0x01, 0x20, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) break;
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) struct vt8623fb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) unsigned int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) /* Calculate the offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (info->var.bits_per_pixel == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) offset = (var->yoffset / 16) * info->var.xres_virtual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) + var->xoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) offset = offset >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) offset = (var->yoffset * info->fix.line_length) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) (var->xoffset * info->var.bits_per_pixel / 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) /* Set the offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) svga_wcrt_multi(par->state.vgabase, vt8623_start_address_regs, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) /* Frame buffer operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) static const struct fb_ops vt8623fb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) .fb_open = vt8623fb_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) .fb_release = vt8623fb_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) .fb_check_var = vt8623fb_check_var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) .fb_set_par = vt8623fb_set_par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) .fb_setcolreg = vt8623fb_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) .fb_blank = vt8623fb_blank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) .fb_pan_display = vt8623fb_pan_display,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) .fb_fillrect = vt8623fb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) .fb_copyarea = cfb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) .fb_imageblit = vt8623fb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) .fb_get_caps = svga_get_caps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) /* PCI probe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) static int vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) struct pci_bus_region bus_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) struct resource vga_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) struct vt8623fb_info *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) unsigned int memsize1, memsize2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) /* Ignore secondary VGA device because there is no VGA arbitration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (! svga_primary_device(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) dev_info(&(dev->dev), "ignoring secondary device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) /* Allocate and fill driver data structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) info = framebuffer_alloc(sizeof(struct vt8623fb_info), &(dev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) mutex_init(&par->open_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) info->flags = FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) info->fbops = &vt8623fb_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) /* Prepare PCI device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) rc = pci_enable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) dev_err(info->device, "cannot enable PCI device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) goto err_enable_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) rc = pci_request_regions(dev, "vt8623fb");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) dev_err(info->device, "cannot reserve framebuffer region\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) goto err_request_regions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) info->fix.smem_start = pci_resource_start(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) info->fix.smem_len = pci_resource_len(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) info->fix.mmio_start = pci_resource_start(dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) info->fix.mmio_len = pci_resource_len(dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) /* Map physical IO memory address into kernel space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) info->screen_base = pci_iomap_wc(dev, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (! info->screen_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) dev_err(info->device, "iomap for framebuffer failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) goto err_iomap_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) par->mmio_base = pci_iomap(dev, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (! par->mmio_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) dev_err(info->device, "iomap for MMIO failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) goto err_iomap_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) bus_reg.start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) bus_reg.end = 64 * 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) vga_res.flags = IORESOURCE_IO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) pcibios_bus_to_resource(dev->bus, &vga_res, &bus_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) par->state.vgabase = (void __iomem *) (unsigned long) vga_res.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) /* Find how many physical memory there is on card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) memsize1 = (vga_rseq(par->state.vgabase, 0x34) + 1) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) memsize2 = vga_rseq(par->state.vgabase, 0x39) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if ((16 <= memsize1) && (memsize1 <= 64) && (memsize1 == memsize2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) info->screen_size = memsize1 << 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) dev_err(info->device, "memory size detection failed (%x %x), suppose 16 MB\n", memsize1, memsize2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) info->screen_size = 16 << 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) info->fix.smem_len = info->screen_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) strcpy(info->fix.id, "VIA VT8623");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) info->fix.type = FB_TYPE_PACKED_PIXELS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) info->fix.ypanstep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) info->fix.accel = FB_ACCEL_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) info->pseudo_palette = (void*)par->pseudo_palette;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) /* Prepare startup mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) kernel_param_lock(THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) kernel_param_unlock(THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (! ((rc == 1) || (rc == 2))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) dev_err(info->device, "mode %s not found\n", mode_option);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) goto err_find_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) rc = fb_alloc_cmap(&info->cmap, 256, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) dev_err(info->device, "cannot allocate colormap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) goto err_alloc_cmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) rc = register_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) dev_err(info->device, "cannot register framebuffer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) goto err_reg_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) fb_info(info, "%s on %s, %d MB RAM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) info->fix.id, pci_name(dev), info->fix.smem_len >> 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) /* Record a reference to the driver data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) pci_set_drvdata(dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (mtrr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) par->wc_cookie = arch_phys_wc_add(info->fix.smem_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) info->fix.smem_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) /* Error handling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) err_reg_fb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) err_alloc_cmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) err_find_mode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) pci_iounmap(dev, par->mmio_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) err_iomap_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) pci_iounmap(dev, info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) err_iomap_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) pci_release_regions(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) err_request_regions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) /* pci_disable_device(dev); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) err_enable_device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) /* PCI remove */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) static void vt8623_pci_remove(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) struct fb_info *info = pci_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if (info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) struct vt8623fb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) arch_phys_wc_del(par->wc_cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) unregister_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) pci_iounmap(dev, info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) pci_iounmap(dev, par->mmio_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) pci_release_regions(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) /* pci_disable_device(dev); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) /* PCI suspend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) static int __maybe_unused vt8623_pci_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) struct fb_info *info = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) struct vt8623fb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) dev_info(info->device, "suspend\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) mutex_lock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (par->ref_count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) fb_set_suspend(info, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) /* PCI resume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) static int __maybe_unused vt8623_pci_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) struct fb_info *info = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) struct vt8623fb_info *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) dev_info(info->device, "resume\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) mutex_lock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (par->ref_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) vt8623fb_set_par(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) fb_set_suspend(info, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) mutex_unlock(&(par->open_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) static const struct dev_pm_ops vt8623_pci_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) .suspend = vt8623_pci_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) .resume = vt8623_pci_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) .freeze = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) .thaw = vt8623_pci_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) .poweroff = vt8623_pci_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) .restore = vt8623_pci_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) #endif /* CONFIG_PM_SLEEP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) /* List of boards that we are trying to support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) static const struct pci_device_id vt8623_devices[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) {PCI_DEVICE(PCI_VENDOR_ID_VIA, 0x3122)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) {0, 0, 0, 0, 0, 0, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) MODULE_DEVICE_TABLE(pci, vt8623_devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) static struct pci_driver vt8623fb_pci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) .name = "vt8623fb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) .id_table = vt8623_devices,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) .probe = vt8623_pci_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) .remove = vt8623_pci_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) .driver.pm = &vt8623_pci_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /* Cleanup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) static void __exit vt8623fb_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) pr_debug("vt8623fb: cleaning up\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) pci_unregister_driver(&vt8623fb_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) /* Driver Initialisation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) static int __init vt8623fb_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) char *option = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (fb_get_options("vt8623fb", &option))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (option && *option)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) mode_option = option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) pr_debug("vt8623fb: initializing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) return pci_register_driver(&vt8623fb_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) /* Modularization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) module_init(vt8623fb_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) module_exit(vt8623fb_cleanup);