📄 mq200fb.c
字号:
if (regno >= 256) return 1; get_color_palette(fb_info, regno, red, green, blue); *red <<= 8; *green <<= 8; *blue <<= 8; *transp = 0; /* right now, transparency is not implemented */ return 0;}/**** * Set a single color register. The values supplied have a 16 bit * magnitude. * Return != 0 for invalid regno. */static int mq200fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ struct mq200fb_info* fb_info = (struct mq200fb_info*)info; if (regno >= 256) return 1; set_color_palette(fb_info, regno, red >> 8, green >> 8, blue >> 8); return 0;}/**** * Pan (or wrap, depending on the `vmode' field) the display using the * `xoffset' and `yoffset' fields of the `var' structure. * If the values don't fit, return -EINVAL. */static int mq200fb_pan_display(const struct fb_var_screeninfo* var, struct fb_info_gen* info){ if (var->xoffset || var->yoffset) return -EINVAL; else return 0;#if 0 if (var->xoffset <= 0 && var->yoffset <= 0) { } else if (var->xoffset > 0 && var->yoffset > 0) { } else if (var->xoffset <= 0 && var->yoffset > 0) { } else { } return 0;#endif}/**** * Blank the screen if blank_mode != 0, else unblank. If blank == NULL * then the caller blanks by setting the CLUT (Color Look Up Table) to all * black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due * to e.g. a video mode which doesn't support it. Implements VESA suspend * and powerdown modes on hardware that supports disabling hsync/vsync: * blank_mode == 2: suspend vsync * blank_mode == 3: suspend hsync * blank_mode == 4: powerdown */static int mq200fb_blank(int blank_mode, struct fb_info_gen* info){ struct mq200fb_info* fb_info = (struct mq200fb_info*)info; if (! fb_info->current_par_valid) return 1; switch (blank_mode) { case 0: enable_dac(fb_info); enable_cursor(fb_info); return 0; case 1: disable_cursor(fb_info); disable_dac(fb_info, WITH_VSYNC | WITH_HSYNC); return 0; case 2: disable_cursor(fb_info); disable_dac(fb_info, WITH_HSYNC); return 0; case 3: disable_cursor(fb_info); disable_dac(fb_info, WITH_VSYNC); return 0; case 4: disable_cursor(fb_info); disable_dac(fb_info, WITH_NONE); return 0; default: printk(CHIPNAME ": unknown blank mode (%d).\n", blank_mode); return 1; }}/**** * Fill in a pointer with the virtual address of the mapped frame buffer. * Fill in a pointer to appropriate low level text console operations (and * optionally a pointer to help data) for the video mode `par' of your * video hardware. These can be generic software routines, or hardware * accelerated routines specifically tailored for your hardware. * If you don't have any appropriate operations, you must fill in a * pointer to dummy operations, and there will be no text output. */static void mq200fb_set_disp(const void *par, struct display *disp, struct fb_info_gen *info){ struct mq200fb_info* fb_info = (struct mq200fb_info*)info; disp->screen_base = (char*)fb_info->regions.v_fb; switch (get_bits_per_pixel((struct mq200fb_par*)par)) {#ifdef FBCON_HAS_CFB8 case 8: disp->dispsw = &mq200_cfb8; break;#endif default: disp->dispsw = &fbcon_dummy; }}/**************************************************************** * functions for struct display_switch member */#ifdef FBCON_HAS_CFB8static voidmq200fb_cursor(struct display* disp, int mode, int x, int y){ struct mq200fb_info* fb_info = (struct mq200fb_info*)disp->fb_info; switch (mode) { case CM_ERASE: disable_cursor(fb_info); break; case CM_DRAW: case CM_MOVE: enable_cursor(fb_info); set_cursor_pos(fb_info, x * fontwidth(disp), y * fontheight(disp)); break; }}#endif#ifdef FBCON_HAS_CFB8static intmq200fb_set_font(struct display* disp, int width, int height){ struct mq200fb_info* fb_info = (struct mq200fb_info*)disp->fb_info; fb_info->cursor_info.size.x = width; fb_info->cursor_info.size.y = height; set_cursor_shape(fb_info); return 1;}#endif#ifdef FBCON_HAS_CFB8static void mq200fb_clear(struct vc_data* conp, struct display* disp, int sy, int sx, int height, int width){ struct mq200fb_info* fb_info = (struct mq200fb_info*)disp->fb_info; u32 bgx; bgx = attr_bgcol_ec(disp, conp); ge_rect_fill(fb_info, sx * fontwidth(disp), sy * fontheight(disp), width * fontwidth(disp), height * fontheight(disp), bgx);}#endif#ifdef FBCON_HAS_CFB8static voidmq200fb_clear_margins(struct vc_data* conp, struct display* disp, int bottom_only){ const struct mq200fb_info* fb_info = (struct mq200fb_info*)disp->fb_info; unsigned int right_start = conp->vc_cols * fontwidth(disp); unsigned int right_width = disp->var.xres - right_start; unsigned int bottom_start = conp->vc_rows * fontheight(disp); unsigned int bottom_width = disp->var.yres - bottom_start; u32 bgx = attr_bgcol_ec(disp, conp); if (! bottom_only && right_width != 0) ge_rect_fill(fb_info, right_start, 0, right_width, disp->var.yres_virtual, bgx); if (bottom_width != 0) ge_rect_fill(fb_info, 0, disp->var.yoffset + bottom_start, right_start, bottom_width, bgx);}#endif#ifdef FBCON_HAS_CFB8static voidmq200fb_putc(struct vc_data* conp, struct display* disp, int ch, int yy, int xx){ struct mq200fb_info* fb_info = (struct mq200fb_info*)disp->fb_info; u32 fgx, bgx; u8* chdat; fgx = attr_fgcol(disp, ch); bgx = attr_bgcol(disp, ch); xx *= fontwidth(disp); yy *= fontheight(disp); chdat = disp->fontdata + (ch & disp->charmask) * fontheight(disp); ge_bitblt_char(fb_info, xx, yy, chdat, fontwidth(disp), fontheight(disp), fgx, bgx);}#endif#ifdef FBCON_HAS_CFB8static voidmq200fb_putcs(struct vc_data* conp, struct display* disp, const unsigned short* str, int count, int yy, int xx){ struct mq200fb_info* fb_info = (struct mq200fb_info*)disp->fb_info; u32 fgx, bgx; fgx = attr_fgcol(disp, scr_readw(str)); bgx = attr_bgcol(disp, scr_readw(str)); xx *= fontwidth(disp); yy *= fontheight(disp); while (count-- > 0) { u16 ch = scr_readw(str++) & disp->charmask; u8* chdat = disp->fontdata + ch * fontheight(disp); ge_bitblt_char(fb_info, xx, yy, chdat, fontwidth(disp), fontheight(disp), fgx, bgx); xx += fontwidth(disp); }}#endif/**************************************************************** * functions related to "struct mq200fb_par". *//**** * Is current window using color palette? */static intis_color_palette_enabled(const struct mq200fb_par* par){ switch (par->gc[0].gcd) { case GCD_1_CP: case GCD_2_CP: case GCD_4_CP: case GCD_8_CP: case GCD_16_CP: case GCD_24_CP: case GCD_32_RGB_CP: case GCD_32_BGR_CP: return 1; default: return 0; }}/**** * Return current window's virtual width in bytes. * * [NOTE] * This function assumes that struct win_par.wst value is not a * negative number. */static u32get_line_length(const struct mq200fb_par* par){ return par->gc[0].win.wst;}/**** * Return current window's width in pixels. */static u32get_width(const struct mq200fb_par* par){ return par->gc[0].win.hww /* + 1 */;}#if 0/**** * set current window's virtual width. * * [NOTE] * This function assumes that already depth was set. */static voidset_v_width(struct mq200fb_par* par, int width) /* in pixels */{ int depth = get_bits_per_pixel(par); par->gc[0].win.wst = (width * depth + 127) / 128 * 16;}#endif/**** * Return current window's virtual height. */static u32get_v_height(const struct mq200fb_par* par){ return par->gc[0].v_height;}static u32get_height(const struct mq200fb_par* par){ return par->gc[0].win.vwh;}#if 0/**** * set current window's virtual height. */static voidset_v_height(struct mq200fb_par* par, int height){ par->gc[0].v_height = height;}#endif/**** * get current window's depth (bits / pixcel). */static intget_bits_per_pixel(const struct mq200fb_par* par){ switch (par->gc[0].gcd) { case GCD_1_CP: return 1; case GCD_2_CP: return 2; case GCD_4_CP: return 4; case GCD_8_CP: return 8; case GCD_16_CP: case GCD_16: return 16; case GCD_24_CP: case GCD_24: return 24; default: return 32; }}#if 0/**** * set current window's depth. * * [NOTE] * we do not use the following: * GCD_16_CP, GCD_24_CP, GCD_32_RGB_CP, GCD_32_BGR_CP, * GCD_32_BGR. */static voidset_bits_per_pixel(struct mq200fb_par* par, int bpp){ if (bpp <= 1) par->gc[0].gcd = GCD_1_CP; else if (bpp <= 2) par->gc[0].gcd = GCD_2_CP; else if (bpp <= 4) par->gc[0].gcd = GCD_4_CP; else if (bpp <= 8) par->gc[0].gcd = GCD_8_CP; else if (bpp <= 16) par->gc[0].gcd = GCD_16; else if (bpp <= 24) par->gc[0].gcd = GCD_24; else par->gc[0].gcd = GCD_32_RGB;}#endifstatic u32get_right_margin(const struct mq200fb_par* par){ return par->gc[0].disp.hss;}static u32get_left_margin(const struct mq200fb_par* par){ return par->gc[0].disp.hdt + 2 - par->gc[0].disp.hse;}static u32get_lower_margin(const struct mq200fb_par* par){ return par->gc[0].disp.vss;}static u32get_upper_margin(const struct mq200fb_par* par){ return par->gc[0].disp.vdt + 1 - par->gc[0].disp.vse;}static u32get_hsync_len(const struct mq200fb_par* par){ return par->gc[0].disp.hse - par->gc[0].disp.hss;}static u32get_vsync_len(const struct mq200fb_par* par){ return par->gc[0].disp.vse - par->gc[0].disp.vss;}static u32get_xoffset(const struct mq200fb_par* par){ return (par->gc[0].win.wsa % par->gc[0].win.wst) / ((get_bits_per_pixel(par) + 7) / 8);}static u32get_yoffset(const struct mq200fb_par* par){ return par->gc[0].win.wsa / par->gc[0].win.wst;}/**** * Return pixel clock in pico seconds. */static u32get_pixclock(const struct mq200fb_par* par){ double freq = get_pll_freq(&par->pll[1]) / get_fd_val(par) / get_sd_val(par); return (u32)(1.0e12 / freq + 0.5);}/**** * Return specified PLL frequencey in MHz. */static doubleget_pll_freq(const struct pll_par* pll){ return 12.288e6 * (pll->m_par + 1) / (pll->n_par + 1) / (1 << pll->p_par);}/**** * Return FD value. FD is a value that is used to generate G1MCLK. */static doubleget_fd_val(const struct mq200fb_par* par){ switch (par->gc[0].fd) { case 0: return 1.0; default: return par->gc[0].fd + 0.5; }}/**** * Return SD value. SD is a value that is used to generate G1MCLK. */static doubleget_sd_val(const struct mq200fb_par* par){ return par->gc[0].sd;}/**************************************************************** * hardware specific functions. *//**** * power state transition to "state". */static voidpower_state_transition(const struct mq200fb_info* fb_info, int state){ int i; writel(state, PMCSR(fb_info)); for (i = 1; ; i++) { udelay(100); if ((readl(PMCSR(fb_info)) & 0x3) == state) { PRINTK(CHIPNAME ": transition to D%d state (%d)\n\r", state, i); break; } }}#if 0/**** * vertical sync enable -- falling edge.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -