📄 intelfbhw.c
字号:
hw->vsync_a = INREG(VSYNC_A); hw->src_size_a = INREG(SRC_SIZE_A); hw->bclrpat_a = INREG(BCLRPAT_A); hw->htotal_b = INREG(HTOTAL_B); hw->hblank_b = INREG(HBLANK_B); hw->hsync_b = INREG(HSYNC_B); hw->vtotal_b = INREG(VTOTAL_B); hw->vblank_b = INREG(VBLANK_B); hw->vsync_b = INREG(VSYNC_B); hw->src_size_b = INREG(SRC_SIZE_B); hw->bclrpat_b = INREG(BCLRPAT_B); if (flag == 3) return flag; hw->adpa = INREG(ADPA); hw->dvoa = INREG(DVOA); hw->dvob = INREG(DVOB); hw->dvoc = INREG(DVOC); hw->dvoa_srcdim = INREG(DVOA_SRCDIM); hw->dvob_srcdim = INREG(DVOB_SRCDIM); hw->dvoc_srcdim = INREG(DVOC_SRCDIM); hw->lvds = INREG(LVDS); if (flag == 4) return flag; hw->pipe_a_conf = INREG(PIPEACONF); hw->pipe_b_conf = INREG(PIPEBCONF); hw->disp_arb = INREG(DISPARB); if (flag == 5) return flag; hw->cursor_a_control = INREG(CURSOR_A_CONTROL); hw->cursor_b_control = INREG(CURSOR_B_CONTROL); hw->cursor_a_base = INREG(CURSOR_A_BASEADDR); hw->cursor_b_base = INREG(CURSOR_B_BASEADDR); if (flag == 6) return flag; for (i = 0; i < 4; i++) { hw->cursor_a_palette[i] = INREG(CURSOR_A_PALETTE0 + (i << 2)); hw->cursor_b_palette[i] = INREG(CURSOR_B_PALETTE0 + (i << 2)); } if (flag == 7) return flag; hw->cursor_size = INREG(CURSOR_SIZE); if (flag == 8) return flag; hw->disp_a_ctrl = INREG(DSPACNTR); hw->disp_b_ctrl = INREG(DSPBCNTR); hw->disp_a_base = INREG(DSPABASE); hw->disp_b_base = INREG(DSPBBASE); hw->disp_a_stride = INREG(DSPASTRIDE); hw->disp_b_stride = INREG(DSPBSTRIDE); if (flag == 9) return flag; hw->vgacntrl = INREG(VGACNTRL); if (flag == 10) return flag; hw->add_id = INREG(ADD_ID); if (flag == 11) return flag; for (i = 0; i < 7; i++) { hw->swf0x[i] = INREG(SWF00 + (i << 2)); hw->swf1x[i] = INREG(SWF10 + (i << 2)); if (i < 3) hw->swf3x[i] = INREG(SWF30 + (i << 2)); } for (i = 0; i < 8; i++) hw->fence[i] = INREG(FENCE + (i << 2)); hw->instpm = INREG(INSTPM); hw->mem_mode = INREG(MEM_MODE); hw->fw_blc_0 = INREG(FW_BLC_0); hw->fw_blc_1 = INREG(FW_BLC_1); hw->hwstam = INREG16(HWSTAM); hw->ier = INREG16(IER); hw->iir = INREG16(IIR); hw->imr = INREG16(IMR); return 0;}static int calc_vclock3(int index, int m, int n, int p){ if (p == 0 || n == 0) return 0; return plls[index].ref_clk * m / n / p;}static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2, int lvds){ struct pll_min_max *pll = &plls[index]; u32 m, vco, p; m = (5 * (m1 + 2)) + (m2 + 2); n += 2; vco = pll->ref_clk * m / n; if (index == PLLS_I8xx) p = ((p1 + 2) * (1 << (p2 + 1))); else p = ((p1) * (p2 ? 5 : 10)); return vco / p;}#if REGDUMPstatic void intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll, int *o_p1, int *o_p2){ int p1, p2; if (IS_I9XX(dinfo)) { if (dpll & DPLL_P1_FORCE_DIV2) p1 = 1; else p1 = (dpll >> DPLL_P1_SHIFT) & 0xff; p1 = ffs(p1); p2 = (dpll >> DPLL_I9XX_P2_SHIFT) & DPLL_P2_MASK; } else { if (dpll & DPLL_P1_FORCE_DIV2) p1 = 0; else p1 = (dpll >> DPLL_P1_SHIFT) & DPLL_P1_MASK; p2 = (dpll >> DPLL_P2_SHIFT) & DPLL_P2_MASK; } *o_p1 = p1; *o_p2 = p2;}#endifvoid intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw){#if REGDUMP int i, m1, m2, n, p1, p2; int index = dinfo->pll_index; DBG_MSG("intelfbhw_print_hw_state\n"); if (!hw) return; /* Read in as much of the HW state as possible. */ printk("hw state dump start\n"); printk(" VGA0_DIVISOR: 0x%08x\n", hw->vga0_divisor); printk(" VGA1_DIVISOR: 0x%08x\n", hw->vga1_divisor); printk(" VGAPD: 0x%08x\n", hw->vga_pd); n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2); printk(" VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", m1, m2, n, p1, p2); printk(" VGA0: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0)); n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2); printk(" VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", m1, m2, n, p1, p2); printk(" VGA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0)); printk(" DPLL_A: 0x%08x\n", hw->dpll_a); printk(" DPLL_B: 0x%08x\n", hw->dpll_b); printk(" FPA0: 0x%08x\n", hw->fpa0); printk(" FPA1: 0x%08x\n", hw->fpa1); printk(" FPB0: 0x%08x\n", hw->fpb0); printk(" FPB1: 0x%08x\n", hw->fpb1); n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2); printk(" PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", m1, m2, n, p1, p2); printk(" PLLA0: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0)); n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2); printk(" PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", m1, m2, n, p1, p2); printk(" PLLA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0));#if 0 printk(" PALETTE_A:\n"); for (i = 0; i < PALETTE_8_ENTRIES) printk(" %3d: 0x%08x\n", i, hw->palette_a[i]); printk(" PALETTE_B:\n"); for (i = 0; i < PALETTE_8_ENTRIES) printk(" %3d: 0x%08x\n", i, hw->palette_b[i]);#endif printk(" HTOTAL_A: 0x%08x\n", hw->htotal_a); printk(" HBLANK_A: 0x%08x\n", hw->hblank_a); printk(" HSYNC_A: 0x%08x\n", hw->hsync_a); printk(" VTOTAL_A: 0x%08x\n", hw->vtotal_a); printk(" VBLANK_A: 0x%08x\n", hw->vblank_a); printk(" VSYNC_A: 0x%08x\n", hw->vsync_a); printk(" SRC_SIZE_A: 0x%08x\n", hw->src_size_a); printk(" BCLRPAT_A: 0x%08x\n", hw->bclrpat_a); printk(" HTOTAL_B: 0x%08x\n", hw->htotal_b); printk(" HBLANK_B: 0x%08x\n", hw->hblank_b); printk(" HSYNC_B: 0x%08x\n", hw->hsync_b); printk(" VTOTAL_B: 0x%08x\n", hw->vtotal_b); printk(" VBLANK_B: 0x%08x\n", hw->vblank_b); printk(" VSYNC_B: 0x%08x\n", hw->vsync_b); printk(" SRC_SIZE_B: 0x%08x\n", hw->src_size_b); printk(" BCLRPAT_B: 0x%08x\n", hw->bclrpat_b); printk(" ADPA: 0x%08x\n", hw->adpa); printk(" DVOA: 0x%08x\n", hw->dvoa); printk(" DVOB: 0x%08x\n", hw->dvob); printk(" DVOC: 0x%08x\n", hw->dvoc); printk(" DVOA_SRCDIM: 0x%08x\n", hw->dvoa_srcdim); printk(" DVOB_SRCDIM: 0x%08x\n", hw->dvob_srcdim); printk(" DVOC_SRCDIM: 0x%08x\n", hw->dvoc_srcdim); printk(" LVDS: 0x%08x\n", hw->lvds); printk(" PIPEACONF: 0x%08x\n", hw->pipe_a_conf); printk(" PIPEBCONF: 0x%08x\n", hw->pipe_b_conf); printk(" DISPARB: 0x%08x\n", hw->disp_arb); printk(" CURSOR_A_CONTROL: 0x%08x\n", hw->cursor_a_control); printk(" CURSOR_B_CONTROL: 0x%08x\n", hw->cursor_b_control); printk(" CURSOR_A_BASEADDR: 0x%08x\n", hw->cursor_a_base); printk(" CURSOR_B_BASEADDR: 0x%08x\n", hw->cursor_b_base); printk(" CURSOR_A_PALETTE: "); for (i = 0; i < 4; i++) { printk("0x%08x", hw->cursor_a_palette[i]); if (i < 3) printk(", "); } printk("\n"); printk(" CURSOR_B_PALETTE: "); for (i = 0; i < 4; i++) { printk("0x%08x", hw->cursor_b_palette[i]); if (i < 3) printk(", "); } printk("\n"); printk(" CURSOR_SIZE: 0x%08x\n", hw->cursor_size); printk(" DSPACNTR: 0x%08x\n", hw->disp_a_ctrl); printk(" DSPBCNTR: 0x%08x\n", hw->disp_b_ctrl); printk(" DSPABASE: 0x%08x\n", hw->disp_a_base); printk(" DSPBBASE: 0x%08x\n", hw->disp_b_base); printk(" DSPASTRIDE: 0x%08x\n", hw->disp_a_stride); printk(" DSPBSTRIDE: 0x%08x\n", hw->disp_b_stride); printk(" VGACNTRL: 0x%08x\n", hw->vgacntrl); printk(" ADD_ID: 0x%08x\n", hw->add_id); for (i = 0; i < 7; i++) { printk(" SWF0%d 0x%08x\n", i, hw->swf0x[i]); } for (i = 0; i < 7; i++) { printk(" SWF1%d 0x%08x\n", i, hw->swf1x[i]); } for (i = 0; i < 3; i++) { printk(" SWF3%d 0x%08x\n", i, hw->swf3x[i]); } for (i = 0; i < 8; i++) printk(" FENCE%d 0x%08x\n", i, hw->fence[i]); printk(" INSTPM 0x%08x\n", hw->instpm); printk(" MEM_MODE 0x%08x\n", hw->mem_mode); printk(" FW_BLC_0 0x%08x\n", hw->fw_blc_0); printk(" FW_BLC_1 0x%08x\n", hw->fw_blc_1); printk(" HWSTAM 0x%04x\n", hw->hwstam); printk(" IER 0x%04x\n", hw->ier); printk(" IIR 0x%04x\n", hw->iir); printk(" IMR 0x%04x\n", hw->imr); printk("hw state dump end\n");#endif}/* Split the M parameter into M1 and M2. */static int splitm(int index, unsigned int m, unsigned int *retm1, unsigned int *retm2){ int m1, m2; int testm; struct pll_min_max *pll = &plls[index]; /* no point optimising too much - brute force m */ for (m1 = pll->min_m1; m1 < pll->max_m1 + 1; m1++) { for (m2 = pll->min_m2; m2 < pll->max_m2 + 1; m2++) { testm = (5 * (m1 + 2)) + (m2 + 2); if (testm == m) { *retm1 = (unsigned int)m1; *retm2 = (unsigned int)m2; return 0; } } } return 1;}/* Split the P parameter into P1 and P2. */static int splitp(int index, unsigned int p, unsigned int *retp1, unsigned int *retp2){ int p1, p2; struct pll_min_max *pll = &plls[index]; if (index == PLLS_I9xx) { p2 = (p % 10) ? 1 : 0; p1 = p / (p2 ? 5 : 10); *retp1 = (unsigned int)p1; *retp2 = (unsigned int)p2; return 0; } if (p % 4 == 0) p2 = 1; else p2 = 0; p1 = (p / (1 << (p2 + 1))) - 2; if (p % 4 == 0 && p1 < pll->min_p1) { p2 = 0; p1 = (p / (1 << (p2 + 1))) - 2; } if (p1 < pll->min_p1 || p1 > pll->max_p1 || (p1 + 2) * (1 << (p2 + 1)) != p) { return 1; } else { *retp1 = (unsigned int)p1; *retp2 = (unsigned int)p2; return 0; }}static int calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1, u32 *retp2, u32 *retclock){ u32 m1, m2, n, p1, p2, n1, testm; u32 f_vco, p, p_best = 0, m, f_out = 0; u32 err_max, err_target, err_best = 10000000; u32 n_best = 0, m_best = 0, f_best, f_err; u32 p_min, p_max, p_inc, div_max; struct pll_min_max *pll = &plls[index]; /* Accept 0.5% difference, but aim for 0.1% */ err_max = 5 * clock / 1000; err_target = clock / 1000; DBG_MSG("Clock is %d\n", clock); div_max = pll->max_vco / clock; p_inc = (clock <= pll->p_transition_clk) ? pll->p_inc_lo : pll->p_inc_hi; p_min = p_inc; p_max = ROUND_DOWN_TO(div_max, p_inc); if (p_min < pll->min_p) p_min = pll->min_p; if (p_max > pll->max_p) p_max = pll->max_p; DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc); p = p_min; do { if (splitp(index, p, &p1, &p2)) { WRN_MSG("cannot split p = %d\n", p); p += p_inc; continue; } n = pll->min_n; f_vco = clock * p; do { m = ROUND_UP_TO(f_vco * n, pll->ref_clk) / pll->ref_clk; if (m < pll->min_m) m = pll->min_m + 1; if (m > pll->max_m) m = pll->max_m - 1; for (testm = m - 1; testm <= m; testm++) { f_out = calc_vclock3(index, testm, n, p); if (splitm(index, testm, &m1, &m2)) { WRN_MSG("cannot split m = %d\n", testm); continue; } if (clock > f_out) f_err = clock - f_out; else/* slightly bias the error for bigger clocks */ f_err = f_out - clock + 1; if (f_err < err_best) { m_best = testm; n_best = n; p_best = p; f_best = f_out; err_best = f_err; } } n++; } while ((n <= pll->max_n) && (f_out >= clock)); p += p_inc; } while ((p <= p_max)); if (!m_best) { WRN_MSG("cannot find parameters for clock %d\n", clock); return 1; } m = m_best; n = n_best; p = p_best; splitm(index, m, &m1, &m2); splitp(index, p, &p1, &p2); n1 = n - 2; DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), " "f: %d (%d), VCO: %d\n", m, m1, m2, n, n1, p, p1, p2, calc_vclock3(index, m, n, p), calc_vclock(index, m1, m2, n1, p1, p2, 0), calc_vclock3(index, m, n, p) * p); *retm1 = m1; *retm2 = m2; *retn = n1; *retp1 = p1; *retp2 = p2; *retclock = calc_vclock(index, m1, m2, n1, p1, p2, 0); return 0;}static __inline__ int check_overflow(u32 value, u32 limit, const char *description){ if (value > limit) { WRN_MSG("%s value %d exceeds limit %d\n", description, value, limit); return 1; } return 0;}/* It is assumed that hw is filled in with the initial state information. */int intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw, struct fb_var_screeninfo *var){ int pipe = PIPE_A; u32 *dpll, *fp0, *fp1; u32 m1, m2, n, p1, p2, clock_target, clock; u32 hsync_start, hsync_end, hblank_start, hblank_end, htotal, hactive; u32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive; u32 vsync_pol, hsync_pol; u32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf; u32 stride_alignment; DBG_MSG("intelfbhw_mode_to_hw\n"); /* Disable VGA */ hw->vgacntrl |= VGA_DISABLE; /* Check whether pipe A or pipe B is enabled. */ if (hw->pipe_a_conf & PIPECONF_ENABLE) pipe = PIPE_A; else if (hw->pipe_b_conf & PIPECONF_ENABLE) pipe = PIPE_B; /* Set which pipe's registers will be set. */ if (pipe == PIPE_B) { dpll = &hw->dpll_b; fp0 = &hw->fpb0; fp1 = &hw->fpb1; hs = &hw->hsync_b; hb = &hw->hblank_b; ht = &hw->htotal_b; vs = &hw->vsync_b; vb = &hw->vblank_b; vt = &hw->vtotal_b; ss = &hw->src_size_b; pipe_conf = &hw->pipe_b_conf; } else { dpll = &hw->dpll_a; fp0 = &hw->fpa0; fp1 = &hw->fpa1; hs = &hw->hsync_a;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -