0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/spinlock.h>
0011 #include <linux/fb.h>
0012 #include <linux/delay.h>
0013 #include <asm/io.h>
0014 #include <asm/div64.h>
0015 #include <asm/delay.h>
0016 #include <linux/cs5535.h>
0017
0018 #include "gxfb.h"
0019
0020 unsigned int gx_frame_buffer_size(void)
0021 {
0022 unsigned int val;
0023
0024 if (!cs5535_has_vsa2()) {
0025 uint32_t hi, lo;
0026
0027
0028 rdmsr(MSR_GLIU_P2D_RO0, lo, hi);
0029
0030
0031 val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20);
0032
0033 val -= (lo & 0x000fffff);
0034 val += 1;
0035
0036
0037 return (val << 12);
0038 }
0039
0040
0041
0042
0043
0044 outw(VSA_VR_UNLOCK, VSA_VRC_INDEX);
0045 outw(VSA_VR_MEM_SIZE, VSA_VRC_INDEX);
0046
0047 val = (unsigned int)(inw(VSA_VRC_DATA)) & 0xFFl;
0048 return (val << 19);
0049 }
0050
0051 int gx_line_delta(int xres, int bpp)
0052 {
0053
0054 return (xres * (bpp >> 3) + 7) & ~0x7;
0055 }
0056
0057 void gx_set_mode(struct fb_info *info)
0058 {
0059 struct gxfb_par *par = info->par;
0060 u32 gcfg, dcfg;
0061 int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal;
0062 int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
0063
0064
0065 write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
0066
0067 gcfg = read_dc(par, DC_GENERAL_CFG);
0068 dcfg = read_dc(par, DC_DISPLAY_CFG);
0069
0070
0071 dcfg &= ~DC_DISPLAY_CFG_TGEN;
0072 write_dc(par, DC_DISPLAY_CFG, dcfg);
0073
0074
0075 udelay(100);
0076
0077
0078 gcfg &= ~(DC_GENERAL_CFG_DFLE | DC_GENERAL_CFG_CMPE |
0079 DC_GENERAL_CFG_DECE);
0080 write_dc(par, DC_GENERAL_CFG, gcfg);
0081
0082
0083 gx_set_dclk_frequency(info);
0084
0085
0086
0087
0088
0089
0090 gcfg &= DC_GENERAL_CFG_YUVM | DC_GENERAL_CFG_VDSE;
0091 dcfg = 0;
0092
0093
0094
0095 gcfg |= (6 << DC_GENERAL_CFG_DFHPEL_SHIFT) |
0096 (5 << DC_GENERAL_CFG_DFHPSL_SHIFT) | DC_GENERAL_CFG_DFLE;
0097
0098
0099 write_dc(par, DC_FB_ST_OFFSET, 0);
0100
0101
0102 write_dc(par, DC_GFX_PITCH, info->fix.line_length >> 3);
0103 write_dc(par, DC_LINE_SIZE,
0104 ((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2);
0105
0106
0107
0108 dcfg |= DC_DISPLAY_CFG_GDEN | DC_DISPLAY_CFG_VDEN |
0109 DC_DISPLAY_CFG_A20M | DC_DISPLAY_CFG_A18M;
0110
0111
0112 switch (info->var.bits_per_pixel) {
0113 case 8:
0114 dcfg |= DC_DISPLAY_CFG_DISP_MODE_8BPP;
0115 break;
0116 case 16:
0117 dcfg |= DC_DISPLAY_CFG_DISP_MODE_16BPP;
0118 break;
0119 case 32:
0120 dcfg |= DC_DISPLAY_CFG_DISP_MODE_24BPP;
0121 dcfg |= DC_DISPLAY_CFG_PALB;
0122 break;
0123 }
0124
0125
0126 dcfg |= DC_DISPLAY_CFG_TGEN;
0127
0128
0129 hactive = info->var.xres;
0130 hblankstart = hactive;
0131 hsyncstart = hblankstart + info->var.right_margin;
0132 hsyncend = hsyncstart + info->var.hsync_len;
0133 hblankend = hsyncend + info->var.left_margin;
0134 htotal = hblankend;
0135
0136 vactive = info->var.yres;
0137 vblankstart = vactive;
0138 vsyncstart = vblankstart + info->var.lower_margin;
0139 vsyncend = vsyncstart + info->var.vsync_len;
0140 vblankend = vsyncend + info->var.upper_margin;
0141 vtotal = vblankend;
0142
0143 write_dc(par, DC_H_ACTIVE_TIMING, (hactive - 1) |
0144 ((htotal - 1) << 16));
0145 write_dc(par, DC_H_BLANK_TIMING, (hblankstart - 1) |
0146 ((hblankend - 1) << 16));
0147 write_dc(par, DC_H_SYNC_TIMING, (hsyncstart - 1) |
0148 ((hsyncend - 1) << 16));
0149
0150 write_dc(par, DC_V_ACTIVE_TIMING, (vactive - 1) |
0151 ((vtotal - 1) << 16));
0152 write_dc(par, DC_V_BLANK_TIMING, (vblankstart - 1) |
0153 ((vblankend - 1) << 16));
0154 write_dc(par, DC_V_SYNC_TIMING, (vsyncstart - 1) |
0155 ((vsyncend - 1) << 16));
0156
0157
0158 write_dc(par, DC_DISPLAY_CFG, dcfg);
0159 write_dc(par, DC_GENERAL_CFG, gcfg);
0160
0161 gx_configure_display(info);
0162
0163
0164 write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
0165 }
0166
0167 void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno,
0168 unsigned red, unsigned green, unsigned blue)
0169 {
0170 struct gxfb_par *par = info->par;
0171 int val;
0172
0173
0174 val = (red << 8) & 0xff0000;
0175 val |= (green) & 0x00ff00;
0176 val |= (blue >> 8) & 0x0000ff;
0177
0178 write_dc(par, DC_PAL_ADDRESS, regno);
0179 write_dc(par, DC_PAL_DATA, val);
0180 }