static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
{
	unsigned long control;
	void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL;

	control = readl(ctrl_reg);

	if (to && (control & SM501_DC_PANEL_CONTROL_VDD) == 0) {
		/* enable panel power */

		control |= SM501_DC_PANEL_CONTROL_VDD;	/* FPVDDEN */
		writel(control, ctrl_reg);
		sm501fb_sync_regs(fbi);
		mdelay(10);

		control |= SM501_DC_PANEL_CONTROL_DATA;	/* DATA */
		writel(control, ctrl_reg);
		sm501fb_sync_regs(fbi);
		mdelay(10);

		control |= SM501_DC_PANEL_CONTROL_BIAS;	/* VBIASEN */
		writel(control, ctrl_reg);
		sm501fb_sync_regs(fbi);
		mdelay(10);

		control |= SM501_DC_PANEL_CONTROL_FPEN;
		writel(control, ctrl_reg);

	} else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) {
		/* disable panel power */

		control &= ~SM501_DC_PANEL_CONTROL_FPEN;
		writel(control, ctrl_reg);
		sm501fb_sync_regs(fbi);
		mdelay(10);

		control &= ~SM501_DC_PANEL_CONTROL_BIAS;
		writel(control, ctrl_reg);
		sm501fb_sync_regs(fbi);
		mdelay(10);

		control &= ~SM501_DC_PANEL_CONTROL_DATA;
		writel(control, ctrl_reg);
		sm501fb_sync_regs(fbi);
		mdelay(10);

		control &= ~SM501_DC_PANEL_CONTROL_VDD;
		writel(control, ctrl_reg);
		sm501fb_sync_regs(fbi);
		mdelay(10);
	}

	sm501fb_sync_regs(fbi);
}
static int sm501fb_pan_pnl(struct fb_var_screeninfo *var,
			   struct fb_info *info)
{
	struct sm501fb_par  *par = info->par;
	struct sm501fb_info *fbi = par->info;
	unsigned long reg;

	reg = var->xoffset | (var->xres_virtual << 16);
	writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH);

	reg = var->yoffset | (var->yres_virtual << 16);
	writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT);

	sm501fb_sync_regs(fbi);
	return 0;
}
static int sm501fb_pan_crt(struct fb_var_screeninfo *var,
			   struct fb_info *info)
{
	struct sm501fb_par  *par = info->par;
	struct sm501fb_info *fbi = par->info;
	unsigned int bytes_pixel = var->bits_per_pixel / 8;
	unsigned long reg;
	unsigned long xoffs;

	xoffs = var->xoffset * bytes_pixel;

	reg = readl(fbi->regs + SM501_DC_CRT_CONTROL);

	reg &= ~SM501_DC_CRT_CONTROL_PIXEL_MASK;
	reg |= ((xoffs & 15) / bytes_pixel) << 4;
	writel(reg, fbi->regs + SM501_DC_CRT_CONTROL);

	reg = (par->screen.sm_addr + xoffs +
	       var->yoffset * info->fix.line_length);
	writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR);

	sm501fb_sync_regs(fbi);
	return 0;
}
static int sm501fb_set_par_pnl(struct fb_info *info)
{
	struct sm501fb_par  *par = info->par;
	struct sm501fb_info *fbi = par->info;
	struct fb_var_screeninfo *var = &info->var;
	unsigned long control;
	unsigned long reg;
	int ret;

	dev_dbg(fbi->dev, "%s(%p)\n", __func__, info);

	/* activate this new configuration */

	ret = sm501fb_set_par_common(info, var);
	if (ret)
		return ret;

	sm501fb_pan_pnl(var, info);
	sm501fb_set_par_geometry(info, var);

	/* update control register */

	control = readl(fbi->regs + SM501_DC_PANEL_CONTROL);
	control &= (SM501_DC_PANEL_CONTROL_GAMMA |
		    SM501_DC_PANEL_CONTROL_VDD  |
		    SM501_DC_PANEL_CONTROL_DATA |
		    SM501_DC_PANEL_CONTROL_BIAS |
		    SM501_DC_PANEL_CONTROL_FPEN |
		    SM501_DC_PANEL_CONTROL_CP |
		    SM501_DC_PANEL_CONTROL_CK |
		    SM501_DC_PANEL_CONTROL_HP |
		    SM501_DC_PANEL_CONTROL_VP |
		    SM501_DC_PANEL_CONTROL_HPD |
		    SM501_DC_PANEL_CONTROL_VPD);

	control |= SM501_FIFO_3;	/* fill if >3 free slots */

	switch(var->bits_per_pixel) {
	case 8:
		control |= SM501_DC_PANEL_CONTROL_8BPP;
		break;

	case 16:
		control |= SM501_DC_PANEL_CONTROL_16BPP;
		break;

	case 32:
		control |= SM501_DC_PANEL_CONTROL_32BPP;
		sm501fb_setup_gamma(fbi, SM501_DC_PANEL_PALETTE);
		break;

	default:
		BUG();
	}

	writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL);

	/* panel plane top left and bottom right location */

	writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC);

	reg  = var->xres - 1;
	reg |= (var->yres - 1) << 16;

	writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC);

	/* program panel control register */

	control |= SM501_DC_PANEL_CONTROL_TE;	/* enable PANEL timing */
	control |= SM501_DC_PANEL_CONTROL_EN;	/* enable PANEL gfx plane */

	if ((var->sync & FB_SYNC_HOR_HIGH_ACT) == 0)
		control |= SM501_DC_PANEL_CONTROL_HSP;

	if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0)
		control |= SM501_DC_PANEL_CONTROL_VSP;

	writel(control, fbi->regs + SM501_DC_PANEL_CONTROL);
	sm501fb_sync_regs(fbi);

	/* power the panel up */
	sm501fb_panel_power(fbi, 1);
	return 0;
}
static int sm501fb_set_par_crt(struct fb_info *info)
{
	struct sm501fb_par  *par = info->par;
	struct sm501fb_info *fbi = par->info;
	struct fb_var_screeninfo *var = &info->var;
	unsigned long control;       /* control register */
	int ret;

	/* activate new configuration */

	dev_dbg(fbi->dev, "%s(%p)\n", __func__, info);

	/* enable CRT DAC - note 0 is on!*/
	sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER);

	control = readl(fbi->regs + SM501_DC_CRT_CONTROL);

	control &= (SM501_DC_CRT_CONTROL_PIXEL_MASK |
		    SM501_DC_CRT_CONTROL_GAMMA |
		    SM501_DC_CRT_CONTROL_BLANK |
		    SM501_DC_CRT_CONTROL_SEL |
		    SM501_DC_CRT_CONTROL_CP |
		    SM501_DC_CRT_CONTROL_TVP);

	/* set the sync polarities before we check data source  */

	if ((var->sync & FB_SYNC_HOR_HIGH_ACT) == 0)
		control |= SM501_DC_CRT_CONTROL_HSP;

	if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0)
		control |= SM501_DC_CRT_CONTROL_VSP;

	if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) {
		/* the head is displaying panel data... */

		sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0);
		goto out_update;
	}

	ret = sm501fb_set_par_common(info, var);
	if (ret) {
		dev_err(fbi->dev, "failed to set common parameters\n");
		return ret;
	}

	sm501fb_pan_crt(var, info);
	sm501fb_set_par_geometry(info, var);

	control |= SM501_FIFO_3;	/* fill if >3 free slots */

	switch(var->bits_per_pixel) {
	case 8:
		control |= SM501_DC_CRT_CONTROL_8BPP;
		break;

	case 16:
		control |= SM501_DC_CRT_CONTROL_16BPP;
		break;

	case 32:
		control |= SM501_DC_CRT_CONTROL_32BPP;
		sm501fb_setup_gamma(fbi, SM501_DC_CRT_PALETTE);
		break;

	default:
		BUG();
	}

	control |= SM501_DC_CRT_CONTROL_SEL;	/* CRT displays CRT data */
	control |= SM501_DC_CRT_CONTROL_TE;	/* enable CRT timing */
	control |= SM501_DC_CRT_CONTROL_ENABLE;	/* enable CRT plane */

 out_update:
	dev_dbg(fbi->dev, "new control is %08lx\n", control);

	writel(control, fbi->regs + SM501_DC_CRT_CONTROL);
	sm501fb_sync_regs(fbi);

	return 0;
}
Beispiel #6
0
static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
{
	unsigned long control;
	void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL;
	struct sm501_platdata_fbsub *pd = fbi->pdata->fb_pnl;

	control = readl(ctrl_reg);

	if (to && (control & SM501_DC_PANEL_CONTROL_VDD) == 0) {
		/* enable panel power */

		control |= SM501_DC_PANEL_CONTROL_VDD;	/* FPVDDEN */
		writel(control, ctrl_reg);
		sm501fb_sync_regs(fbi);
		mdelay(10);

		control |= SM501_DC_PANEL_CONTROL_DATA;	/* DATA */
		writel(control, ctrl_reg);
		sm501fb_sync_regs(fbi);
		mdelay(10);

		/* VBIASEN */

		if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
			if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN)
				control &= ~SM501_DC_PANEL_CONTROL_BIAS;
			else
				control |= SM501_DC_PANEL_CONTROL_BIAS;

			writel(control, ctrl_reg);
			sm501fb_sync_regs(fbi);
			mdelay(10);
		}

		if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
			if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN)
				control &= ~SM501_DC_PANEL_CONTROL_FPEN;
			else
				control |= SM501_DC_PANEL_CONTROL_FPEN;

			writel(control, ctrl_reg);
			sm501fb_sync_regs(fbi);
			mdelay(10);
		}
	} else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) {
		/* disable panel power */
		if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) {
			if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN)
				control |= SM501_DC_PANEL_CONTROL_FPEN;
			else
				control &= ~SM501_DC_PANEL_CONTROL_FPEN;

			writel(control, ctrl_reg);
			sm501fb_sync_regs(fbi);
			mdelay(10);
		}

		if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) {
			if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN)
				control |= SM501_DC_PANEL_CONTROL_BIAS;
			else
				control &= ~SM501_DC_PANEL_CONTROL_BIAS;

			writel(control, ctrl_reg);
			sm501fb_sync_regs(fbi);
			mdelay(10);
		}

		control &= ~SM501_DC_PANEL_CONTROL_DATA;
		writel(control, ctrl_reg);
		sm501fb_sync_regs(fbi);
		mdelay(10);

		control &= ~SM501_DC_PANEL_CONTROL_VDD;
		writel(control, ctrl_reg);
		sm501fb_sync_regs(fbi);
		mdelay(10);
	}

	sm501fb_sync_regs(fbi);
}