Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4fdc325 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'fbdev-updates-for-3.6' of git://github.com/schandinat/linux-2.6

Pull fbdev updates from Florian Tobias Schandinat:
 - large updates for OMAP
   - support for LCD3 overlay manager (omap5)
   - omapdss output cleanup
   - removal of passive matrix LCD support as there are no drivers for
     such panels for DSS or DSS2 and nobody complained (cleanup)
 - large updates for SH Mobile
   - overlay support
   - separating MERAM (cache) from framebuffer driver
 - some updates for Exynos and da8xx-fb
 - various other small patches

* tag 'fbdev-updates-for-3.6' of git://github.com/schandinat/linux-2.6: (78 commits)
  da8xx-fb: fix compile issue due to missing include
  fbdev: Make pixel_to_pat() failure mode more friendly
  da8xx-fb: do not turn ON LCD backlight unless LCDC is enabled
  fbdev: sh_mobile_lcdc: Fix vertical panning step
  video: exynos mipi dsi: Fix mipi dsi regulators handling issue
  video: da8xx-fb: do clock reset of revision 2 LCDC before enabling
  arm: da850: configure LCDC fifo threshold
  video: da8xx-fb: configure FIFO threshold to reduce underflow errors
  video: da8xx-fb: fix flicker due to 1 frame delay in updated frame
  video: da8xx-fb rev2: fix disabling of palette completion interrupt
  da8xx-fb: add missing FB_BLANK operations
  video: exynos_dp: use usleep_range instead of delay
  video: exynos_dp: check the only INTERLANE_ALIGN_DONE bit during Link Training
  fb: epson1355fb: Fix section mismatch
  video: exynos_dp: fix wrong DPCD address during Link Training
  video/smscufx: fix line counting in fb_write
  aty128fb: Fix coding style issues
  fbdev: sh_mobile_lcdc: Fix pan offset computation in YUV mode
  fbdev: sh_mobile_lcdc: Fix overlay registers update during pan operation
  fbdev: sh_mobile_lcdc: Support horizontal panning
  ...
parents 9a51cf28 a0239073
Loading
Loading
Loading
Loading
+44 −0
Original line number Original line Diff line number Diff line
What:		/sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_alpha
Date:		May 2012
Contact:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Description:
		This file is only available on fb[0-9] devices corresponding
		to overlay planes.

		Stores the alpha blending value for the overlay. Values range
		from 0 (transparent) to 255 (opaque). The value is ignored if
		the mode is not set to Alpha Blending.

What:		/sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_mode
Date:		May 2012
Contact:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Description:
		This file is only available on fb[0-9] devices corresponding
		to overlay planes.

		Selects the composition mode for the overlay. Possible values
		are

		0 - Alpha Blending
		1 - ROP3

What:		/sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_position
Date:		May 2012
Contact:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Description:
		This file is only available on fb[0-9] devices corresponding
		to overlay planes.

		Stores the x,y overlay position on the display in pixels. The
		position format is `[0-9]+,[0-9]+'.

What:		/sys/devices/platform/sh_mobile_lcdc_fb.[0-3]/graphics/fb[0-9]/ovl_rop3
Date:		May 2012
Contact:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Description:
		This file is only available on fb[0-9] devices corresponding
		to overlay planes.

		Stores the raster operation (ROP3) for the overlay. Values
		range from 0 to 255. The value is ignored if the mode is not
		set to ROP3.
+1 −0
Original line number Original line Diff line number Diff line
@@ -546,6 +546,7 @@ static struct lcd_ctrl_config lcd_cfg = {
	.sync_edge		= 0,
	.sync_edge		= 0,
	.sync_ctrl		= 1,
	.sync_ctrl		= 1,
	.raster_order		= 0,
	.raster_order		= 0,
	.fifo_th		= 6,
};
};


struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata = {
struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata = {
+21 −4
Original line number Original line Diff line number Diff line
@@ -37,6 +37,7 @@


#define DISPC_CONTROL		0x0040
#define DISPC_CONTROL		0x0040
#define DISPC_CONTROL2		0x0238
#define DISPC_CONTROL2		0x0238
#define DISPC_CONTROL3		0x0848
#define DISPC_IRQSTATUS		0x0018
#define DISPC_IRQSTATUS		0x0018


#define DSS_SYSCONFIG		0x10
#define DSS_SYSCONFIG		0x10
@@ -52,6 +53,7 @@
#define EVSYNC_EVEN_IRQ_SHIFT	2
#define EVSYNC_EVEN_IRQ_SHIFT	2
#define EVSYNC_ODD_IRQ_SHIFT	3
#define EVSYNC_ODD_IRQ_SHIFT	3
#define FRAMEDONE2_IRQ_SHIFT	22
#define FRAMEDONE2_IRQ_SHIFT	22
#define FRAMEDONE3_IRQ_SHIFT	30
#define FRAMEDONETV_IRQ_SHIFT	24
#define FRAMEDONETV_IRQ_SHIFT	24


/*
/*
@@ -376,7 +378,7 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
static void dispc_disable_outputs(void)
static void dispc_disable_outputs(void)
{
{
	u32 v, irq_mask = 0;
	u32 v, irq_mask = 0;
	bool lcd_en, digit_en, lcd2_en = false;
	bool lcd_en, digit_en, lcd2_en = false, lcd3_en = false;
	int i;
	int i;
	struct omap_dss_dispc_dev_attr *da;
	struct omap_dss_dispc_dev_attr *da;
	struct omap_hwmod *oh;
	struct omap_hwmod *oh;
@@ -405,7 +407,13 @@ static void dispc_disable_outputs(void)
		lcd2_en = v & LCD_EN_MASK;
		lcd2_en = v & LCD_EN_MASK;
	}
	}


	if (!(lcd_en | digit_en | lcd2_en))
	/* store value of LCDENABLE for LCD3 */
	if (da->manager_count > 3) {
		v = omap_hwmod_read(oh, DISPC_CONTROL3);
		lcd3_en = v & LCD_EN_MASK;
	}

	if (!(lcd_en | digit_en | lcd2_en | lcd3_en))
		return; /* no managers currently enabled */
		return; /* no managers currently enabled */


	/*
	/*
@@ -426,10 +434,12 @@ static void dispc_disable_outputs(void)


	if (lcd2_en)
	if (lcd2_en)
		irq_mask |= 1 << FRAMEDONE2_IRQ_SHIFT;
		irq_mask |= 1 << FRAMEDONE2_IRQ_SHIFT;
	if (lcd3_en)
		irq_mask |= 1 << FRAMEDONE3_IRQ_SHIFT;


	/*
	/*
	 * clear any previous FRAMEDONE, FRAMEDONETV,
	 * clear any previous FRAMEDONE, FRAMEDONETV,
	 * EVSYNC_EVEN/ODD or FRAMEDONE2 interrupts
	 * EVSYNC_EVEN/ODD, FRAMEDONE2 or FRAMEDONE3 interrupts
	 */
	 */
	omap_hwmod_write(irq_mask, oh, DISPC_IRQSTATUS);
	omap_hwmod_write(irq_mask, oh, DISPC_IRQSTATUS);


@@ -445,12 +455,19 @@ static void dispc_disable_outputs(void)
		omap_hwmod_write(v, oh, DISPC_CONTROL2);
		omap_hwmod_write(v, oh, DISPC_CONTROL2);
	}
	}


	/* disable LCD3 manager */
	if (da->manager_count > 3) {
		v = omap_hwmod_read(oh, DISPC_CONTROL3);
		v &= ~LCD_EN_MASK;
		omap_hwmod_write(v, oh, DISPC_CONTROL3);
	}

	i = 0;
	i = 0;
	while ((omap_hwmod_read(oh, DISPC_IRQSTATUS) & irq_mask) !=
	while ((omap_hwmod_read(oh, DISPC_IRQSTATUS) & irq_mask) !=
	       irq_mask) {
	       irq_mask) {
		i++;
		i++;
		if (i > FRAMEDONE_IRQ_TIMEOUT) {
		if (i > FRAMEDONE_IRQ_TIMEOUT) {
			pr_err("didn't get FRAMEDONE1/2 or TV interrupt\n");
			pr_err("didn't get FRAMEDONE1/2/3 or TV interrupt\n");
			break;
			break;
		}
		}
		mdelay(1);
		mdelay(1);
+101 −79
Original line number Original line Diff line number Diff line
@@ -90,7 +90,8 @@
#undef DEBUG
#undef DEBUG


#ifdef DEBUG
#ifdef DEBUG
#define DBG(fmt, args...)		printk(KERN_DEBUG "aty128fb: %s " fmt, __func__, ##args);
#define DBG(fmt, args...) \
	printk(KERN_DEBUG "aty128fb: %s " fmt, __func__, ##args);
#else
#else
#define DBG(fmt, args...)
#define DBG(fmt, args...)
#endif
#endif
@@ -450,7 +451,8 @@ static int aty128_decode_var(struct fb_var_screeninfo *var,
#if 0
#if 0
static void __devinit aty128_get_pllinfo(struct aty128fb_par *par,
static void __devinit aty128_get_pllinfo(struct aty128fb_par *par,
					 void __iomem *bios);
					 void __iomem *bios);
static void __devinit __iomem *aty128_map_ROM(struct pci_dev *pdev, const struct aty128fb_par *par);
static void __devinit __iomem *aty128_map_ROM(struct pci_dev *pdev,
					      const struct aty128fb_par *par);
#endif
#endif
static void aty128_timings(struct aty128fb_par *par);
static void aty128_timings(struct aty128fb_par *par);
static void aty128_init_engine(struct aty128fb_par *par);
static void aty128_init_engine(struct aty128fb_par *par);
@@ -779,7 +781,8 @@ static u32 depth_to_dst(u32 depth)




#ifndef __sparc__
#ifndef __sparc__
static void __iomem * __devinit aty128_map_ROM(const struct aty128fb_par *par, struct pci_dev *dev)
static void __iomem * __devinit aty128_map_ROM(const struct aty128fb_par *par,
					       struct pci_dev *dev)
{
{
	u16 dptr;
	u16 dptr;
	u8 rom_type;
	u8 rom_type;
@@ -811,13 +814,14 @@ static void __iomem * __devinit aty128_map_ROM(const struct aty128fb_par *par, s
	/* Look for the PCI data to check the ROM type */
	/* Look for the PCI data to check the ROM type */
	dptr = BIOS_IN16(0x18);
	dptr = BIOS_IN16(0x18);


	/* Check the PCI data signature. If it's wrong, we still assume a normal x86 ROM
	/* Check the PCI data signature. If it's wrong, we still assume a normal
	 * for now, until I've verified this works everywhere. The goal here is more
	 * x86 ROM for now, until I've verified this works everywhere.
	 * to phase out Open Firmware images.
	 * The goal here is more to phase out Open Firmware images.
	 *
	 *
	 * Currently, we only look at the first PCI data, we could iteratre and deal with
	 * Currently, we only look at the first PCI data, we could iteratre and
	 * them all, and we should use fb_bios_start relative to start of image and not
	 * deal with them all, and we should use fb_bios_start relative to start
	 * relative start of ROM, but so far, I never found a dual-image ATI card
	 * of image and not relative start of ROM, but so far, I never found a
	 * dual-image ATI card.
	 *
	 *
	 * typedef struct {
	 * typedef struct {
	 * 	u32	signature;	+ 0x00
	 * 	u32	signature;	+ 0x00
@@ -852,7 +856,8 @@ static void __iomem * __devinit aty128_map_ROM(const struct aty128fb_par *par, s
		printk(KERN_INFO "aty128fb: Found HP PA-RISC ROM Image\n");
		printk(KERN_INFO "aty128fb: Found HP PA-RISC ROM Image\n");
		goto failed;
		goto failed;
	default:
	default:
		printk(KERN_INFO "aty128fb: Found unknown type %d ROM Image\n", rom_type);
		printk(KERN_INFO "aty128fb: Found unknown type %d ROM Image\n",
		       rom_type);
		goto failed;
		goto failed;
	}
	}
 anyway:
 anyway:
@@ -863,7 +868,8 @@ static void __iomem * __devinit aty128_map_ROM(const struct aty128fb_par *par, s
	return NULL;
	return NULL;
}
}


static void __devinit aty128_get_pllinfo(struct aty128fb_par *par, unsigned char __iomem *bios)
static void __devinit aty128_get_pllinfo(struct aty128fb_par *par,
					 unsigned char __iomem *bios)
{
{
	unsigned int bios_hdr;
	unsigned int bios_hdr;
	unsigned int bios_pll;
	unsigned int bios_pll;
@@ -1247,10 +1253,13 @@ static int aty128_crtc_to_var(const struct aty128_crtc *crtc,
static void aty128_set_crt_enable(struct aty128fb_par *par, int on)
static void aty128_set_crt_enable(struct aty128fb_par *par, int on)
{
{
	if (on) {
	if (on) {
		aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) | CRT_CRTC_ON);
		aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) |
		aty_st_le32(DAC_CNTL, (aty_ld_le32(DAC_CNTL) | DAC_PALETTE2_SNOOP_EN));
			    CRT_CRTC_ON);
		aty_st_le32(DAC_CNTL, (aty_ld_le32(DAC_CNTL) |
			    DAC_PALETTE2_SNOOP_EN));
	} else
	} else
		aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) & ~CRT_CRTC_ON);
		aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) &
			    ~CRT_CRTC_ON);
}
}


static void aty128_set_lcd_enable(struct aty128fb_par *par, int on)
static void aty128_set_lcd_enable(struct aty128fb_par *par, int on)
@@ -1281,7 +1290,8 @@ static void aty128_set_lcd_enable(struct aty128fb_par *par, int on)
	}
	}
}
}


static void aty128_set_pll(struct aty128_pll *pll, const struct aty128fb_par *par)
static void aty128_set_pll(struct aty128_pll *pll,
			   const struct aty128fb_par *par)
{
{
	u32 div3;
	u32 div3;


@@ -1366,7 +1376,8 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
}
}




static int aty128_pll_to_var(const struct aty128_pll *pll, struct fb_var_screeninfo *var)
static int aty128_pll_to_var(const struct aty128_pll *pll,
			     struct fb_var_screeninfo *var)
{
{
	var->pixclock = 100000000 / pll->vclk;
	var->pixclock = 100000000 / pll->vclk;


@@ -1512,7 +1523,8 @@ static int aty128fb_set_par(struct fb_info *info)
 *  encode/decode the User Defined Part of the Display
 *  encode/decode the User Defined Part of the Display
 */
 */


static int aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par)
static int aty128_decode_var(struct fb_var_screeninfo *var,
			     struct aty128fb_par *par)
{
{
	int err;
	int err;
	struct aty128_crtc crtc;
	struct aty128_crtc crtc;
@@ -1559,7 +1571,8 @@ static int aty128_encode_var(struct fb_var_screeninfo *var,
}           
}           




static int aty128fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static int aty128fb_check_var(struct fb_var_screeninfo *var,
			      struct fb_info *info)
{
{
	struct aty128fb_par par;
	struct aty128fb_par par;
	int err;
	int err;
@@ -1575,7 +1588,8 @@ static int aty128fb_check_var(struct fb_var_screeninfo *var, struct fb_info *inf
/*
/*
 *  Pan or Wrap the Display
 *  Pan or Wrap the Display
 */
 */
static int aty128fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fb) 
static int aty128fb_pan_display(struct fb_var_screeninfo *var,
				struct fb_info *fb)
{
{
	struct aty128fb_par *par = fb->par;
	struct aty128fb_par *par = fb->par;
	u32 xoffset, yoffset;
	u32 xoffset, yoffset;
@@ -1594,7 +1608,8 @@ static int aty128fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *f
	par->crtc.xoffset = xoffset;
	par->crtc.xoffset = xoffset;
	par->crtc.yoffset = yoffset;
	par->crtc.yoffset = yoffset;


	offset = ((yoffset * par->crtc.vxres + xoffset)*(par->crtc.bpp >> 3)) & ~7;
	offset = ((yoffset * par->crtc.vxres + xoffset) * (par->crtc.bpp >> 3))
									  & ~7;


	if (par->crtc.bpp == 24)
	if (par->crtc.bpp == 24)
		offset += 8 * (offset % 3); /* Must be multiple of 8 and 3 */
		offset += 8 * (offset % 3); /* Must be multiple of 8 and 3 */
@@ -1620,11 +1635,13 @@ static void aty128_st_pal(u_int regno, u_int red, u_int green, u_int blue,
		 * do mirroring
		 * do mirroring
		 */
		 */


		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);
		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) |
			    DAC_PALETTE_ACCESS_CNTL);
		aty_st_8(PALETTE_INDEX, regno);
		aty_st_8(PALETTE_INDEX, regno);
		aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue);
		aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue);
#endif
#endif
		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);
		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) &
			    ~DAC_PALETTE_ACCESS_CNTL);
	}
	}


	aty_st_8(PALETTE_INDEX, regno);
	aty_st_8(PALETTE_INDEX, regno);
@@ -1753,7 +1770,8 @@ static int aty128_bl_update_status(struct backlight_device *bd)
			aty_st_le32(LVDS_GEN_CNTL, reg);
			aty_st_le32(LVDS_GEN_CNTL, reg);
		}
		}
		reg &= ~LVDS_BL_MOD_LEVEL_MASK;
		reg &= ~LVDS_BL_MOD_LEVEL_MASK;
		reg |= (aty128_bl_get_level_brightness(par, level) << LVDS_BL_MOD_LEVEL_SHIFT);
		reg |= (aty128_bl_get_level_brightness(par, level) <<
			LVDS_BL_MOD_LEVEL_SHIFT);
#ifdef BACKLIGHT_LVDS_OFF
#ifdef BACKLIGHT_LVDS_OFF
		reg |= LVDS_ON | LVDS_EN;
		reg |= LVDS_ON | LVDS_EN;
		reg &= ~LVDS_DISPLAY_DIS;
		reg &= ~LVDS_DISPLAY_DIS;
@@ -1764,7 +1782,8 @@ static int aty128_bl_update_status(struct backlight_device *bd)
#endif
#endif
	} else {
	} else {
		reg &= ~LVDS_BL_MOD_LEVEL_MASK;
		reg &= ~LVDS_BL_MOD_LEVEL_MASK;
		reg |= (aty128_bl_get_level_brightness(par, 0) << LVDS_BL_MOD_LEVEL_SHIFT);
		reg |= (aty128_bl_get_level_brightness(par, 0) <<
			LVDS_BL_MOD_LEVEL_SHIFT);
#ifdef BACKLIGHT_LVDS_OFF
#ifdef BACKLIGHT_LVDS_OFF
		reg |= LVDS_DISPLAY_DIS;
		reg |= LVDS_DISPLAY_DIS;
		aty_st_le32(LVDS_GEN_CNTL, reg);
		aty_st_le32(LVDS_GEN_CNTL, reg);
@@ -1869,7 +1888,8 @@ static void aty128_early_resume(void *data)
}
}
#endif /* CONFIG_PPC_PMAC */
#endif /* CONFIG_PPC_PMAC */


static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
static int __devinit aty128_init(struct pci_dev *pdev,
				 const struct pci_device_id *ent)
{
{
	struct fb_info *info = pci_get_drvdata(pdev);
	struct fb_info *info = pci_get_drvdata(pdev);
	struct aty128fb_par *par = info->par;
	struct aty128fb_par *par = info->par;
@@ -1887,7 +1907,8 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i


	/* range check to make sure */
	/* range check to make sure */
	if (ent->driver_data < ARRAY_SIZE(r128_family))
	if (ent->driver_data < ARRAY_SIZE(r128_family))
	    strlcat(video_card, r128_family[ent->driver_data], sizeof(video_card));
		strlcat(video_card, r128_family[ent->driver_data],
			sizeof(video_card));


	printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev);
	printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev);


@@ -1911,11 +1932,11 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i
		/* Indicate sleep capability */
		/* Indicate sleep capability */
		if (par->chip_gen == rage_M3) {
		if (par->chip_gen == rage_M3) {
			pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1);
			pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1);
#if 0 /* Disable the early video resume hack for now as it's causing problems, among
#if 0 /* Disable the early video resume hack for now as it's causing problems,
       * others we now rely on the PCI core restoring the config space for us, which
       * among others we now rely on the PCI core restoring the config space
       * isn't the case with that hack, and that code path causes various things to
       * for us, which isn't the case with that hack, and that code path causes
       * be called with interrupts off while they shouldn't. I'm leaving the code in
       * various things to be called with interrupts off while they shouldn't.
       * as it can be useful for debugging purposes
       * I'm leaving the code in as it can be useful for debugging purposes
       */
       */
			pmac_set_early_video_resume(aty128_early_resume, par);
			pmac_set_early_video_resume(aty128_early_resume, par);
#endif
#endif
@@ -2018,7 +2039,8 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i


#ifdef CONFIG_PCI
#ifdef CONFIG_PCI
/* register a card    ++ajoshi */
/* register a card    ++ajoshi */
static int __devinit aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
static int __devinit aty128_probe(struct pci_dev *pdev,
				  const struct pci_device_id *ent)
{
{
	unsigned long fb_addr, reg_addr;
	unsigned long fb_addr, reg_addr;
	struct aty128fb_par *par;
	struct aty128fb_par *par;
@@ -2358,8 +2380,8 @@ static inline void aty128_rectcopy(int srcx, int srcy, int dstx, int dsty,
     * Text mode accelerated functions
     * Text mode accelerated functions
     */
     */


static void fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, int dx,
static void fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy,
			int height, int width)
			       int dx, int height, int width)
{
{
	sx     *= fontwidth(p);
	sx     *= fontwidth(p);
	sy     *= fontheight(p);
	sy     *= fontheight(p);
+60 −18
Original line number Original line Diff line number Diff line
@@ -30,7 +30,10 @@
#include <linux/clk.h>
#include <linux/clk.h>
#include <linux/cpufreq.h>
#include <linux/cpufreq.h>
#include <linux/console.h>
#include <linux/console.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/lcm.h>
#include <video/da8xx-fb.h>
#include <video/da8xx-fb.h>
#include <asm/div64.h>
#include <asm/div64.h>


@@ -160,6 +163,13 @@ struct da8xx_fb_par {
	wait_queue_head_t	vsync_wait;
	wait_queue_head_t	vsync_wait;
	int			vsync_flag;
	int			vsync_flag;
	int			vsync_timeout;
	int			vsync_timeout;
	spinlock_t		lock_for_chan_update;

	/*
	 * LCDC has 2 ping pong DMA channels, channel 0
	 * and channel 1.
	 */
	unsigned int		which_dma_channel_done;
#ifdef CONFIG_CPU_FREQ
#ifdef CONFIG_CPU_FREQ
	struct notifier_block	freq_transition;
	struct notifier_block	freq_transition;
	unsigned int		lcd_fck_rate;
	unsigned int		lcd_fck_rate;
@@ -260,10 +270,18 @@ static inline void lcd_enable_raster(void)
{
{
	u32 reg;
	u32 reg;


	/* Put LCDC in reset for several cycles */
	if (lcd_revision == LCD_VERSION_2)
		/* Write 1 to reset LCDC */
		lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG);
	mdelay(1);

	/* Bring LCDC out of reset */
	/* Bring LCDC out of reset */
	if (lcd_revision == LCD_VERSION_2)
	if (lcd_revision == LCD_VERSION_2)
		lcdc_write(0, LCD_CLK_RESET_REG);
		lcdc_write(0, LCD_CLK_RESET_REG);
	mdelay(1);


	/* Above reset sequence doesnot reset register context */
	reg = lcdc_read(LCD_RASTER_CTRL_REG);
	reg = lcdc_read(LCD_RASTER_CTRL_REG);
	if (!(reg & LCD_RASTER_ENABLE))
	if (!(reg & LCD_RASTER_ENABLE))
		lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
		lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
@@ -277,10 +295,6 @@ static inline void lcd_disable_raster(void)
	reg = lcdc_read(LCD_RASTER_CTRL_REG);
	reg = lcdc_read(LCD_RASTER_CTRL_REG);
	if (reg & LCD_RASTER_ENABLE)
	if (reg & LCD_RASTER_ENABLE)
		lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
		lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);

	if (lcd_revision == LCD_VERSION_2)
		/* Write 1 to reset LCDC */
		lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG);
}
}


static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
@@ -344,8 +358,8 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
	lcd_enable_raster();
	lcd_enable_raster();
}
}


/* Configure the Burst Size of DMA */
/* Configure the Burst Size and fifo threhold of DMA */
static int lcd_cfg_dma(int burst_size)
static int lcd_cfg_dma(int burst_size, int fifo_th)
{
{
	u32 reg;
	u32 reg;


@@ -369,6 +383,9 @@ static int lcd_cfg_dma(int burst_size)
	default:
	default:
		return -EINVAL;
		return -EINVAL;
	}
	}

	reg |= (fifo_th << 8);

	lcdc_write(reg, LCD_DMA_CTRL_REG);
	lcdc_write(reg, LCD_DMA_CTRL_REG);


	return 0;
	return 0;
@@ -670,8 +687,8 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
		lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) &
		lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) &
			~LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);
			~LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG);


	/* Configure the DMA burst size. */
	/* Configure the DMA burst size and fifo threshold. */
	ret = lcd_cfg_dma(cfg->dma_burst_sz);
	ret = lcd_cfg_dma(cfg->dma_burst_sz, cfg->fifo_th);
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;


@@ -715,7 +732,6 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
{
{
	struct da8xx_fb_par *par = arg;
	struct da8xx_fb_par *par = arg;
	u32 stat = lcdc_read(LCD_MASKED_STAT_REG);
	u32 stat = lcdc_read(LCD_MASKED_STAT_REG);
	u32 reg_int;


	if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
	if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
		lcd_disable_raster();
		lcd_disable_raster();
@@ -732,10 +748,8 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)


		lcdc_write(stat, LCD_MASKED_STAT_REG);
		lcdc_write(stat, LCD_MASKED_STAT_REG);


		/* Disable PL completion inerrupt */
		/* Disable PL completion interrupt */
		reg_int = lcdc_read(LCD_INT_ENABLE_CLR_REG) |
		lcdc_write(LCD_V2_PL_INT_ENA, LCD_INT_ENABLE_CLR_REG);
		       (LCD_V2_PL_INT_ENA);
		lcdc_write(reg_int, LCD_INT_ENABLE_CLR_REG);


		/* Setup and start data loading mode */
		/* Setup and start data loading mode */
		lcd_blit(LOAD_DATA, par);
		lcd_blit(LOAD_DATA, par);
@@ -743,6 +757,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
		lcdc_write(stat, LCD_MASKED_STAT_REG);
		lcdc_write(stat, LCD_MASKED_STAT_REG);


		if (stat & LCD_END_OF_FRAME0) {
		if (stat & LCD_END_OF_FRAME0) {
			par->which_dma_channel_done = 0;
			lcdc_write(par->dma_start,
			lcdc_write(par->dma_start,
				   LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
				   LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
			lcdc_write(par->dma_end,
			lcdc_write(par->dma_end,
@@ -752,6 +767,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
		}
		}


		if (stat & LCD_END_OF_FRAME1) {
		if (stat & LCD_END_OF_FRAME1) {
			par->which_dma_channel_done = 1;
			lcdc_write(par->dma_start,
			lcdc_write(par->dma_start,
				   LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
				   LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
			lcdc_write(par->dma_end,
			lcdc_write(par->dma_end,
@@ -798,6 +814,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
		lcdc_write(stat, LCD_STAT_REG);
		lcdc_write(stat, LCD_STAT_REG);


		if (stat & LCD_END_OF_FRAME0) {
		if (stat & LCD_END_OF_FRAME0) {
			par->which_dma_channel_done = 0;
			lcdc_write(par->dma_start,
			lcdc_write(par->dma_start,
				   LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
				   LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
			lcdc_write(par->dma_end,
			lcdc_write(par->dma_end,
@@ -807,6 +824,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
		}
		}


		if (stat & LCD_END_OF_FRAME1) {
		if (stat & LCD_END_OF_FRAME1) {
			par->which_dma_channel_done = 1;
			lcdc_write(par->dma_start,
			lcdc_write(par->dma_start,
				   LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
				   LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
			lcdc_write(par->dma_end,
			lcdc_write(par->dma_end,
@@ -1021,11 +1039,14 @@ static int cfb_blank(int blank, struct fb_info *info)
	par->blank = blank;
	par->blank = blank;
	switch (blank) {
	switch (blank) {
	case FB_BLANK_UNBLANK:
	case FB_BLANK_UNBLANK:
		lcd_enable_raster();

		if (par->panel_power_ctrl)
		if (par->panel_power_ctrl)
			par->panel_power_ctrl(1);
			par->panel_power_ctrl(1);

		lcd_enable_raster();
		break;
		break;
	case FB_BLANK_NORMAL:
	case FB_BLANK_VSYNC_SUSPEND:
	case FB_BLANK_HSYNC_SUSPEND:
	case FB_BLANK_POWERDOWN:
	case FB_BLANK_POWERDOWN:
		if (par->panel_power_ctrl)
		if (par->panel_power_ctrl)
			par->panel_power_ctrl(0);
			par->panel_power_ctrl(0);
@@ -1052,6 +1073,7 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var,
	struct fb_fix_screeninfo    *fix = &fbi->fix;
	struct fb_fix_screeninfo    *fix = &fbi->fix;
	unsigned int end;
	unsigned int end;
	unsigned int start;
	unsigned int start;
	unsigned long irq_flags;


	if (var->xoffset != fbi->var.xoffset ||
	if (var->xoffset != fbi->var.xoffset ||
			var->yoffset != fbi->var.yoffset) {
			var->yoffset != fbi->var.yoffset) {
@@ -1069,6 +1091,21 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var,
			end	= start + fbi->var.yres * fix->line_length - 1;
			end	= start + fbi->var.yres * fix->line_length - 1;
			par->dma_start	= start;
			par->dma_start	= start;
			par->dma_end	= end;
			par->dma_end	= end;
			spin_lock_irqsave(&par->lock_for_chan_update,
					irq_flags);
			if (par->which_dma_channel_done == 0) {
				lcdc_write(par->dma_start,
					   LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
				lcdc_write(par->dma_end,
					   LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
			} else if (par->which_dma_channel_done == 1) {
				lcdc_write(par->dma_start,
					   LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
				lcdc_write(par->dma_end,
					   LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
			}
			spin_unlock_irqrestore(&par->lock_for_chan_update,
					irq_flags);
		}
		}
	}
	}


@@ -1114,6 +1151,7 @@ static int __devinit fb_probe(struct platform_device *device)
	struct da8xx_fb_par *par;
	struct da8xx_fb_par *par;
	resource_size_t len;
	resource_size_t len;
	int ret, i;
	int ret, i;
	unsigned long ulcm;


	if (fb_pdata == NULL) {
	if (fb_pdata == NULL) {
		dev_err(&device->dev, "Can not get platform data\n");
		dev_err(&device->dev, "Can not get platform data\n");
@@ -1209,7 +1247,8 @@ static int __devinit fb_probe(struct platform_device *device)


	/* allocate frame buffer */
	/* allocate frame buffer */
	par->vram_size = lcdc_info->width * lcdc_info->height * lcd_cfg->bpp;
	par->vram_size = lcdc_info->width * lcdc_info->height * lcd_cfg->bpp;
	par->vram_size = PAGE_ALIGN(par->vram_size/8);
	ulcm = lcm((lcdc_info->width * lcd_cfg->bpp)/8, PAGE_SIZE);
	par->vram_size = roundup(par->vram_size/8, ulcm);
	par->vram_size = par->vram_size * LCD_NUM_BUFFERS;
	par->vram_size = par->vram_size * LCD_NUM_BUFFERS;


	par->vram_virt = dma_alloc_coherent(NULL,
	par->vram_virt = dma_alloc_coherent(NULL,
@@ -1296,6 +1335,8 @@ static int __devinit fb_probe(struct platform_device *device)
	/* initialize the vsync wait queue */
	/* initialize the vsync wait queue */
	init_waitqueue_head(&par->vsync_wait);
	init_waitqueue_head(&par->vsync_wait);
	par->vsync_timeout = HZ / 5;
	par->vsync_timeout = HZ / 5;
	par->which_dma_channel_done = -1;
	spin_lock_init(&par->lock_for_chan_update);


	/* Register the Frame Buffer  */
	/* Register the Frame Buffer  */
	if (register_framebuffer(da8xx_fb_info) < 0) {
	if (register_framebuffer(da8xx_fb_info) < 0) {
@@ -1382,11 +1423,12 @@ static int fb_resume(struct platform_device *dev)
	struct da8xx_fb_par *par = info->par;
	struct da8xx_fb_par *par = info->par;


	console_lock();
	console_lock();
	clk_enable(par->lcdc_clk);
	lcd_enable_raster();

	if (par->panel_power_ctrl)
	if (par->panel_power_ctrl)
		par->panel_power_ctrl(1);
		par->panel_power_ctrl(1);


	clk_enable(par->lcdc_clk);
	lcd_enable_raster();
	fb_set_suspend(info, 0);
	fb_set_suspend(info, 0);
	console_unlock();
	console_unlock();


Loading