/* TODO * Support panel scaling * Add acceleration * Add support for interlacing (TV out) * Support compression
*/
/* This is the complete list of PLL frequencies that we can set - * we will choose the closest match to the incoming clock. * freq is the frequency of the dotclock * 1000 (for example, * 24823 = 24.983 Mhz). * pllval is the corresponding PLL value
*/
if (info->fix.line_length > 4096)
dv = DC_DV_CTL_DV_LINE_SIZE_8K; elseif (info->fix.line_length > 2048)
dv = DC_DV_CTL_DV_LINE_SIZE_4K; elseif (info->fix.line_length > 1024)
dv = DC_DV_CTL_DV_LINE_SIZE_2K; else
dv = DC_DV_CTL_DV_LINE_SIZE_1K;
max = info->fix.line_length * info->var.yres;
max = (max + 0x3FF) & 0xFFFFFC00;
write_dc(par, DC_DV_TOP, max | DC_DV_TOP_DV_TOP_EN);
val = read_dc(par, DC_DV_CTL) & ~DC_DV_CTL_DV_LINE_SIZE;
write_dc(par, DC_DV_CTL, val | dv);
/* save the display controller palette */
write_dc(par, DC_PAL_ADDRESS, 0); for (i = 0; i < ARRAY_SIZE(par->dc_pal); i++)
par->dc_pal[i] = read_dc(par, DC_PAL_DATA);
/* save the video processor palette */
write_vp(par, VP_PAR, 0); for (i = 0; i < ARRAY_SIZE(par->vp_pal); i++)
par->vp_pal[i] = read_vp(par, VP_PDR);
/* save the horizontal filter coefficients */
filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL; for (i = 0; i < ARRAY_SIZE(par->hcoeff); i += 2) {
write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);
par->hcoeff[i] = read_dc(par, DC_FILT_COEFF1);
par->hcoeff[i + 1] = read_dc(par, DC_FILT_COEFF2);
}
/* save the vertical filter coefficients */
filt &= ~DC_IRQ_FILT_CTL_H_FILT_SEL; for (i = 0; i < ARRAY_SIZE(par->vcoeff); i++) {
write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);
par->vcoeff[i] = read_dc(par, DC_FILT_COEFF1);
}
/* save video coeff ram */
memcpy(par->vp_coeff, par->vp_regs + VP_VCR, sizeof(par->vp_coeff));
}
staticvoid lx_restore_gfx_proc(struct lxfb_par *par)
{ int i;
/* a bunch of registers require GP_RASTER_MODE to be set first */
write_gp(par, GP_RASTER_MODE, par->gp[GP_RASTER_MODE]);
for (i = 0; i < ARRAY_SIZE(par->gp); i++) { switch (i) { case GP_RASTER_MODE: case GP_VECTOR_MODE: case GP_BLT_MODE: case GP_BLT_STATUS: case GP_HST_SRC: /* FIXME: restore LUT data */ case GP_LUT_INDEX: case GP_LUT_DATA: /* don't restore these registers */ break;
default:
write_gp(par, i, par->gp[i]);
}
}
}
staticvoid lx_restore_display_ctlr(struct lxfb_par *par)
{
uint32_t filt; int i;
wrmsrq(MSR_LX_SPARE_MSR, par->msr.dcspare);
for (i = 0; i < ARRAY_SIZE(par->dc); i++) { switch (i) { case DC_UNLOCK: /* unlock the DC; runs first */
write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK); break;
case DC_GENERAL_CFG: case DC_DISPLAY_CFG: /* disable all while restoring */
write_dc(par, i, 0); break;
case DC_DV_CTL: /* set all ram to dirty */
write_dc(par, i, par->dc[i] | DC_DV_CTL_CLEAR_DV_RAM); break;
case DC_RSVD_1: case DC_RSVD_2: case DC_RSVD_3: case DC_LINE_CNT: case DC_PAL_ADDRESS: case DC_PAL_DATA: case DC_DFIFO_DIAG: case DC_CFIFO_DIAG: case DC_FILT_COEFF1: case DC_FILT_COEFF2: case DC_RSVD_4: case DC_RSVD_5: /* don't restore these registers */ break;
default:
write_dc(par, i, par->dc[i]);
}
}
/* restore the palette */
write_dc(par, DC_PAL_ADDRESS, 0); for (i = 0; i < ARRAY_SIZE(par->dc_pal); i++)
write_dc(par, DC_PAL_DATA, par->dc_pal[i]);
/* restore the horizontal filter coefficients */
filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL; for (i = 0; i < ARRAY_SIZE(par->hcoeff); i += 2) {
write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);
write_dc(par, DC_FILT_COEFF1, par->hcoeff[i]);
write_dc(par, DC_FILT_COEFF2, par->hcoeff[i + 1]);
}
/* restore the vertical filter coefficients */
filt &= ~DC_IRQ_FILT_CTL_H_FILT_SEL; for (i = 0; i < ARRAY_SIZE(par->vcoeff); i++) {
write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);
write_dc(par, DC_FILT_COEFF1, par->vcoeff[i]);
}
}
staticvoid lx_restore_video_proc(struct lxfb_par *par)
{ int i;
for (i = 0; i < ARRAY_SIZE(par->vp); i++) { switch (i) { case VP_VCFG: case VP_DCFG: case VP_PAR: case VP_PDR: case VP_CCS: case VP_RSVD_0: /* case VP_VDC: */ /* why should this not be restored? */ case VP_RSVD_1: case VP_CRC32: /* don't restore these registers */ break;
default:
write_vp(par, i, par->vp[i]);
}
}
/* restore video processor palette */
write_vp(par, VP_PAR, 0); for (i = 0; i < ARRAY_SIZE(par->vp_pal); i++)
write_vp(par, VP_PDR, par->vp_pal[i]);
/* Flat Panel */ for (i = 0; i < ARRAY_SIZE(par->fp); i++) { switch (i) { case FP_PM: case FP_RSVD_0: case FP_RSVD_1: case FP_RSVD_2: case FP_RSVD_3: case FP_RSVD_4: /* don't restore these registers */ break;
default:
write_fp(par, i, par->fp[i]);
}
}
/* control the panel */ if (par->fp[FP_PM] & FP_PM_P) { /* power on the panel if not already power{ed,ing} on */ if (!(read_fp(par, FP_PM) &
(FP_PM_PANEL_ON|FP_PM_PANEL_PWR_UP)))
write_fp(par, FP_PM, par->fp[FP_PM]);
} else { /* power down the panel if not already power{ed,ing} down */ if (!(read_fp(par, FP_PM) &
(FP_PM_PANEL_OFF|FP_PM_PANEL_PWR_DOWN)))
write_fp(par, FP_PM, par->fp[FP_PM]);
}
/* turn everything on */
write_vp(par, VP_VCFG, par->vp[VP_VCFG]);
write_vp(par, VP_DCFG, par->vp[VP_DCFG]);
write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG]); /* do this last; it will enable the FIFO load */
write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG]);
/* lock the door behind us */
write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
}
int lx_powerdown(struct fb_info *info)
{ struct lxfb_par *par = info->par;
if (par->powered_down) return 0;
lx_save_regs(par);
lx_graphics_disable(info);
par->powered_down = 1; return 0;
}
int lx_powerup(struct fb_info *info)
{ struct lxfb_par *par = info->par;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.