Exemple #1
0
/*!
 * @brief Config and request LCDC interrupt
 */
static void _request_irq(void)
{
	unsigned long status;
	unsigned long flags;

	/* Read to clear the status */
	status = __raw_readl(LCDC_REG(LCDC_LISR));

	if (request_irq(MXC_INT_LCDC, mx2fb_isr, 0, "LCDC", 0))
		pr_info("Request LCDC IRQ failed.\n");
	else {
		spin_lock_irqsave(&mx2fb_notifier_list.lock, flags);

		/* Enable interrupt in case client has registered */
		if (mx2fb_notifier_list.head != NULL) {
			unsigned long status;
			unsigned long ints = MX2FB_INT_EOF;

			ints |= MX2FB_INT_GW_EOF;

			/* Read to clear the status */
			status = __raw_readl(LCDC_REG(LCDC_LISR));

			/* Configure interrupt condition for EOF */
			__raw_writel(0x0, LCDC_REG(LCDC_LICR));

			/* Enable EOF and graphic window EOF interrupt */
			__raw_writel(ints, LCDC_REG(LCDC_LIER));
		}

		spin_unlock_irqrestore(&mx2fb_notifier_list.lock, flags);
	}
}
Exemple #2
0
/*!
 * @brief Register a client notifier
 * @param nb	notifier block to callback on events
 */
int mx2fb_register_client(struct notifier_block *nb)
{
	unsigned long flags;
	int ret;

	ret = atomic_notifier_chain_register(&mx2fb_notifier_list, nb);

	spin_lock_irqsave(&mx2fb_notifier_list.lock, flags);

	/* Enable interrupt in case client has registered */
	if (mx2fb_notifier_list.head != NULL) {
		unsigned long status;
		unsigned long ints = MX2FB_INT_EOF;

		ints |= MX2FB_INT_GW_EOF;

		/* Read to clear the status */
		status = __raw_readl(LCDC_REG(LCDC_LISR));

		/* Configure interrupt condition for EOF */
		__raw_writel(0x0, LCDC_REG(LCDC_LICR));

		/* Enable EOF and graphic window EOF interrupt */
		__raw_writel(ints, LCDC_REG(LCDC_LIER));
	}

	spin_unlock_irqrestore(&mx2fb_notifier_list.lock, flags);

	return ret;
}
Exemple #3
0
/*!
 * @brief Free LCDC interrupt handler
 */
static void _free_irq(void)
{
	/* Disable all LCDC interrupt */
	__raw_writel(0x0, LCDC_REG(LCDC_LIER));

	free_irq(MXC_INT_LCDC, 0);
}
Exemple #4
0
/*!
 * @brief Disable graphic window.
 * @param info	framebuffer information pointer
 */
static void _disable_graphic_window(struct fb_info *info)
{
	unsigned long i = 0;

	g_gwinfo.enabled = 0;

	/*
	 * Set alpha value to zero and reduce gw size, otherwise the graphic
	 * window will not be able to be enabled again.
	 */
	__raw_writel(__raw_readl(LCDC_REG(LCDC_LGWCR)) & 0x00FFFFFF,
		     LCDC_REG(LCDC_LGWCR));
	__raw_writel(((16 >> 4) << 20) + 16, LCDC_REG(LCDC_LGWSR));
	while (i < 1000)
		i++;

	/* Now disable graphic window */
	__raw_writel(__raw_readl(LCDC_REG(LCDC_LGWCR)) & ~0x00400000,
		     LCDC_REG(LCDC_LGWCR));

	dev_dbg(info->device, "Graphic window disabled.\n");
}
Exemple #5
0
/*!
 * @brief Unregister a client notifier
 * @param nb	notifier block to callback on events
 */
int mx2fb_unregister_client(struct notifier_block *nb)
{
	unsigned long flags;
	int ret;

	ret = atomic_notifier_chain_unregister(&mx2fb_notifier_list, nb);

	spin_lock_irqsave(&mx2fb_notifier_list.lock, flags);

	/* Mask interrupt in case no client registered */
	if (mx2fb_notifier_list.head == NULL)
		__raw_writel(0x0, LCDC_REG(LCDC_LIER));

	spin_unlock_irqrestore(&mx2fb_notifier_list.lock, flags);

	return ret;
}
Exemple #6
0
/*
 * @brief LCDC interrupt handler
 */
static irqreturn_t mx2fb_isr(int irq, void *dev_id)
{
	struct fb_event event;
	unsigned long status = __raw_readl(LCDC_REG(LCDC_LISR));

	if (status & MX2FB_INT_EOF) {
		event.info = &mx2fb_info[0];
		atomic_notifier_call_chain(&mx2fb_notifier_list,
					   FB_EVENT_MXC_EOF, &event);
	}

	if (status & MX2FB_INT_GW_EOF) {
		event.info = &mx2fb_info[1];
		atomic_notifier_call_chain(&mx2fb_notifier_list,
					   FB_EVENT_MXC_EOF, &event);
	}

	return IRQ_HANDLED;
}
Exemple #7
0
/*!
 * @brief Setup graphic window properties.
 * @param gwinfo	graphic window information pointer
 */
void mx2_gw_set(struct fb_gwinfo *gwinfo)
{
	int width, height, xpos, ypos;
	int width_bg, height_bg;
	unsigned long lgwcr = 0x00400000;	/* Graphic window control register */

	if (!gwinfo->enabled) {
		_disable_graphic_window(0);
		return;
	}

	/* Graphic window start address register */
	__raw_writel(gwinfo->base, LCDC_REG(LCDC_LGWSAR));

	/*
	 * The graphic window width, height, x position and y position
	 * must be synced up width the background window, otherwise there
	 * may be flickering.
	 */
	width_bg = (__raw_readl(LCDC_REG(LCDC_LSR)) & 0x03F00000) >> 16;
	height_bg = __raw_readl(LCDC_REG(LCDC_LSR)) & 0x000003FF;

	width = (gwinfo->xres > width_bg) ? width_bg : gwinfo->xres;
	height = (gwinfo->yres > height_bg) ? height_bg : gwinfo->yres;

	xpos = gwinfo->xpos;
	ypos = gwinfo->ypos;

	if (xpos + width > width_bg)
		xpos = width_bg - width;
	if (ypos + height > height_bg)
		ypos = height_bg - height;

	/* Graphic window size register */
	__raw_writel(((width >> 4) << 20) + height, LCDC_REG(LCDC_LGWSR));

	/* Graphic window virtual page width register */
	__raw_writel(gwinfo->xres_virtual >> 1, LCDC_REG(LCDC_LGWVPWR));

	/* Graphic window position register */
	__raw_writel(((xpos & 0x000003FF) << 16) | (ypos & 0x000003FF),
		     LCDC_REG(LCDC_LGWPR));

	/* Graphic window panning offset register */
	__raw_writel(0, LCDC_REG(LCDC_LGWPOR));

	/* Graphic window DMA control register */
	if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0)
		__raw_writel(0x00040060, LCDC_REG(LCDC_LGWDCR));
	else
		__raw_writel(0x00020010, LCDC_REG(LCDC_LGWDCR));

	/* Graphic window control register */
	lgwcr |= (gwinfo->alpha_value & 0x000000FF) << 24;
	lgwcr |= gwinfo->ck_enabled ? 0x00800000 : 0;
	lgwcr |= gwinfo->vs_reversed ? 0x00200000 : 0;

	/*
	 * Color keying value
	 * Todo: assume always use RGB565
	 */
	lgwcr |= (gwinfo->ck_red & 0x0000003F) << 12;
	lgwcr |= (gwinfo->ck_green & 0x0000003F) << 6;
	lgwcr |= gwinfo->ck_blue & 0x0000003F;

	__raw_writel(lgwcr, LCDC_REG(LCDC_LGWCR));

	pr_debug("Graphic window enabled.\n");
}
Exemple #8
0
/*!
 * @brief Set LCD brightness
 * @param level	brightness level
 */
void mx2fb_set_brightness(uint8_t level)
{
	/* Set LCDC PWM contract control register */
	__raw_writel(0x00A90300 | level, LCDC_REG(LCDC_LPCCR));
}
Exemple #9
0
/*!
 * @brief Update LCDC registers
 * @param info	framebuffer information pointer
 */
static void _update_lcdc(struct fb_info *info)
{
	unsigned long base;
	unsigned long perclk3, pcd, pcr;
	struct fb_var_screeninfo *var = &info->var;
	struct mx2fb_info *mx2fbi = (struct mx2fb_info *)info->par;

	if (mx2fbi->type == MX2FB_TYPE_GW) {
		_enable_graphic_window(info);
		return;
	}

	base = (var->yoffset * var->xres_virtual + var->xoffset);
	base *= (var->bits_per_pixel) / 8;
	base += info->fix.smem_start;

	/* Screen start address register */
	__raw_writel(base, LCDC_REG(LCDC_LSSAR));

	/* Size register */
	dev_dbg(info->device, "xres = %d, yres = %d\n",
		info->var.xres, info->var.yres);
	__raw_writel(((info->var.xres >> 4) << 20) + info->var.yres,
		     LCDC_REG(LCDC_LSR));

	/* Virtual page width register */
	__raw_writel(info->var.xres_virtual >> 1, LCDC_REG(LCDC_LVPWR));

	/* To setup LCDC pixel clock */
	perclk3 = clk_round_rate(lcdc_clk, 134000000);
	if (clk_set_rate(lcdc_clk, perclk3)) {
		printk(KERN_INFO "mx2fb: Unable to set clock to %lu\n",
		       perclk3);
		perclk3 = clk_get_rate(lcdc_clk);
	}

	/* Calculate pixel clock divider, and round to the nearest integer */
	pcd = (perclk3 * 8 / (PICOS2KHZ(var->pixclock) * 1000UL) + 4) / 8;
	if (--pcd > 0x3F)
		pcd = 0x3F;

	/* Panel configuration register */
	pcr = 0xFA008B80 | pcd;
	pcr |= (var->sync & FB_SYNC_CLK_INVERT) ? 0x01000000 : 0;
	pcr |= (var->sync & FB_SYNC_SHARP_MODE) ? 0x00000040 : 0;
	pcr |= (var->sync & FB_SYNC_OE_ACT_HIGH) ? 0 : 0x00100000;
	__raw_writel(pcr, LCDC_REG(LCDC_LPCR));

	/* Horizontal and vertical configuration register */
	__raw_writel(((var->hsync_len - 1) << 26)
		     + ((var->right_margin - 1) << 8)
		     + (var->left_margin - 3), LCDC_REG(LCDC_LHCR));
	__raw_writel((var->vsync_len << 26)
		     + (var->lower_margin << 8)
		     + var->upper_margin, LCDC_REG(LCDC_LVCR));

	/* Sharp configuration register */
	__raw_writel(0x00120300, LCDC_REG(LCDC_LSCR));

	/* Refresh mode control reigster */
	__raw_writel(0x00000000, LCDC_REG(LCDC_LRMCR));

	/* DMA control register */
	if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0)
		__raw_writel(0x00040060, LCDC_REG(LCDC_LDCR));
	else
		__raw_writel(0x00020010, LCDC_REG(LCDC_LDCR));
}
Exemple #10
0
/*!
 * @brief Set LCD brightness
 * @param level	brightness level
 */
static void _set_brightness(unsigned char level)
{
	/* Set LCDC PWM contract control register */
	__raw_writel(0x00A90300 | level, LCDC_REG(LCDC_LPCCR));
}