<commit_before>/*
 *  Driver for AT91/AT32 LCD Controller
 *
 *  Copyright (C) 2007 Atmel Corporation
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file COPYING in the main directory of this archive for
 * more details.
 */

#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/backlight.h>

#include <mach/board.h>
#include <mach/cpu.h>
#include <mach/gpio.h>

#include <video/atmel_lcdc.h>

#define lcdc_readl(sinfo, reg)		__raw_readl((sinfo)->mmio+(reg))
#define lcdc_writel(sinfo, reg, val)	__raw_writel((val), (sinfo)->mmio+(reg))

/* configurable parameters */
#define ATMEL_LCDC_CVAL_DEFAULT		0xc8
#define ATMEL_LCDC_DMA_BURST_LEN	8

#if defined(CONFIG_ARCH_AT91SAM9263) || defined(CONFIG_ARCH_AT91CAP9) || \
	defined(CONFIG_ARCH_AT91SAM9RL)
#define ATMEL_LCDC_FIFO_SIZE		2048
#else
#define ATMEL_LCDC_FIFO_SIZE		512
#endif

#if defined(CONFIG_ARCH_AT91)
#define	ATMEL_LCDFB_FBINFO_DEFAULT	FBINFO_DEFAULT

static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
					struct fb_var_screeninfo *var)
{

}
#elif defined(CONFIG_AVR32)
#define	ATMEL_LCDFB_FBINFO_DEFAULT	(FBINFO_DEFAULT \
					| FBINFO_PARTIAL_PAN_OK \
					| FBINFO_HWACCEL_XPAN \
					| FBINFO_HWACCEL_YPAN)

static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
				     struct fb_var_screeninfo *var)
{
	u32 dma2dcfg;
	u32 pixeloff;

	pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f;

	dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8;
	dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
	lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);

	/* Update configuration */
	lcdc_writel(sinfo, ATMEL_LCDC_DMACON,
		    lcdc_readl(sinfo, ATMEL_LCDC_DMACON)
		    | ATMEL_LCDC_DMAUPDT);
}
#endif

static const u32 contrast_ctr = ATMEL_LCDC_PS_DIV8
		| ATMEL_LCDC_POL_POSITIVE
		| ATMEL_LCDC_ENA_PWMENABLE;

#ifdef CONFIG_BACKLIGHT_ATMEL_LCDC

/* some bl->props field just changed */
static int atmel_bl_update_status(struct backlight_device *bl)
{
	struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
	int			power = sinfo->bl_power;
	int			brightness = bl->props.brightness;

	/* REVISIT there may be a meaningful difference between
	 * fb_blank and power ... there seem to be some cases
	 * this doesn't handle correctly.
	 */
	if (bl->props.fb_blank != sinfo->bl_power)
		power = bl->props.fb_blank;
	else if (bl->props.power != sinfo->bl_power)
		power = bl->props.power;

	if (brightness < 0 && power == FB_BLANK_UNBLANK)
		brightness = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
	else if (power != FB_BLANK_UNBLANK)
		brightness = 0;

	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness);
	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR,
			brightness ? contrast_ctr : 0);

	bl->props.fb_blank = bl->props.power = sinfo->bl_power = power;

	return 0;
}

static int atmel_bl_get_brightness(struct backlight_device *bl)
{
	struct atmel_lcdfb_info *sinfo = bl_get_data(bl);

	return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
}

static struct backlight_ops atmel_lcdc_bl_ops = {
	.update_status = atmel_bl_update_status,
	.get_brightness = atmel_bl_get_brightness,
};

static void init_backlight(struct atmel_lcdfb_info *sinfo)
{
	struct backlight_device	*bl;

	sinfo->bl_power = FB_BLANK_UNBLANK;

	if (sinfo->backlight)
		return;

	bl = backlight_device_register("backlight", &sinfo->pdev->dev,
			sinfo, &atmel_lcdc_bl_ops);
	if (IS_ERR(sinfo->backlight)) {
		dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n",
				PTR_ERR(bl));
		return;
	}
	sinfo->backlight = bl;

	bl->props.power = FB_BLANK_UNBLANK;
	bl->props.fb_blank = FB_BLANK_UNBLANK;
	bl->props.max_brightness = 0xff;
	bl->props.brightness = atmel_bl_get_brightness(bl);
}

static void exit_backlight(struct atmel_lcdfb_info *sinfo)
{
	if (sinfo->backlight)
		backlight_device_unregister(sinfo->backlight);
}

#else

static void init_backlight(struct atmel_lcdfb_info *sinfo)
{
	dev_warn(&sinfo->pdev->dev, "backlight control is not available\n");
}

static void exit_backlight(struct atmel_lcdfb_info *sinfo)
{
}

#endif

static void init_contrast(struct atmel_lcdfb_info *sinfo)
{
	/* have some default contrast/backlight settings */
	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);

	if (sinfo->lcdcon_is_backlight)
		init_backlight(sinfo);
}


static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = {
	.type		= FB_TYPE_PACKED_PIXELS,
	.visual		= FB_VISUAL_TRUECOLOR,
	.xpanstep	= 0,
	.ypanstep	= 0,
	.ywrapstep	= 0,
	.accel		= FB_ACCEL_NONE,
};<commit_msg>atmel_lcdfb: set ypanstep to 1 and enable y-panning on AT91<commit_after>/*
 *  Driver for AT91/AT32 LCD Controller
 *
 *  Copyright (C) 2007 Atmel Corporation
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file COPYING in the main directory of this archive for
 * more details.
 */

#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/backlight.h>

#include <mach/board.h>
#include <mach/cpu.h>
#include <mach/gpio.h>

#include <video/atmel_lcdc.h>

#define lcdc_readl(sinfo, reg)		__raw_readl((sinfo)->mmio+(reg))
#define lcdc_writel(sinfo, reg, val)	__raw_writel((val), (sinfo)->mmio+(reg))

/* configurable parameters */
#define ATMEL_LCDC_CVAL_DEFAULT		0xc8
#define ATMEL_LCDC_DMA_BURST_LEN	8

#if defined(CONFIG_ARCH_AT91SAM9263) || defined(CONFIG_ARCH_AT91CAP9) || \
	defined(CONFIG_ARCH_AT91SAM9RL)
#define ATMEL_LCDC_FIFO_SIZE		2048
#else
#define ATMEL_LCDC_FIFO_SIZE		512
#endif

#if defined(CONFIG_ARCH_AT91)
#define	ATMEL_LCDFB_FBINFO_DEFAULT	(FBINFO_DEFAULT \
					 | FBINFO_PARTIAL_PAN_OK \
					 | FBINFO_HWACCEL_YPAN)

static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
					struct fb_var_screeninfo *var)
{

}
#elif defined(CONFIG_AVR32)
#define	ATMEL_LCDFB_FBINFO_DEFAULT	(FBINFO_DEFAULT \
					| FBINFO_PARTIAL_PAN_OK \
					| FBINFO_HWACCEL_XPAN \
					| FBINFO_HWACCEL_YPAN)

static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
				     struct fb_var_screeninfo *var)
{
	u32 dma2dcfg;
	u32 pixeloff;

	pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f;

	dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8;
	dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
	lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);

	/* Update configuration */
	lcdc_writel(sinfo, ATMEL_LCDC_DMACON,
		    lcdc_readl(sinfo, ATMEL_LCDC_DMACON)
		    | ATMEL_LCDC_DMAUPDT);
}
#endif

static const u32 contrast_ctr = ATMEL_LCDC_PS_DIV8
		| ATMEL_LCDC_POL_POSITIVE
		| ATMEL_LCDC_ENA_PWMENABLE;

#ifdef CONFIG_BACKLIGHT_ATMEL_LCDC

/* some bl->props field just changed */
static int atmel_bl_update_status(struct backlight_device *bl)
{
	struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
	int			power = sinfo->bl_power;
	int			brightness = bl->props.brightness;

	/* REVISIT there may be a meaningful difference between
	 * fb_blank and power ... there seem to be some cases
	 * this doesn't handle correctly.
	 */
	if (bl->props.fb_blank != sinfo->bl_power)
		power = bl->props.fb_blank;
	else if (bl->props.power != sinfo->bl_power)
		power = bl->props.power;

	if (brightness < 0 && power == FB_BLANK_UNBLANK)
		brightness = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
	else if (power != FB_BLANK_UNBLANK)
		brightness = 0;

	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness);
	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR,
			brightness ? contrast_ctr : 0);

	bl->props.fb_blank = bl->props.power = sinfo->bl_power = power;

	return 0;
}

static int atmel_bl_get_brightness(struct backlight_device *bl)
{
	struct atmel_lcdfb_info *sinfo = bl_get_data(bl);

	return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
}

static struct backlight_ops atmel_lcdc_bl_ops = {
	.update_status = atmel_bl_update_status,
	.get_brightness = atmel_bl_get_brightness,
};

static void init_backlight(struct atmel_lcdfb_info *sinfo)
{
	struct backlight_device	*bl;

	sinfo->bl_power = FB_BLANK_UNBLANK;

	if (sinfo->backlight)
		return;

	bl = backlight_device_register("backlight", &sinfo->pdev->dev,
			sinfo, &atmel_lcdc_bl_ops);
	if (IS_ERR(sinfo->backlight)) {
		dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n",
				PTR_ERR(bl));
		return;
	}
	sinfo->backlight = bl;

	bl->props.power = FB_BLANK_UNBLANK;
	bl->props.fb_blank = FB_BLANK_UNBLANK;
	bl->props.max_brightness = 0xff;
	bl->props.brightness = atmel_bl_get_brightness(bl);
}

static void exit_backlight(struct atmel_lcdfb_info *sinfo)
{
	if (sinfo->backlight)
		backlight_device_unregister(sinfo->backlight);
}

#else

static void init_backlight(struct atmel_lcdfb_info *sinfo)
{
	dev_warn(&sinfo->pdev->dev, "backlight control is not available\n");
}

static void exit_backlight(struct atmel_lcdfb_info *sinfo)
{
}

#endif

static void init_contrast(struct atmel_lcdfb_info *sinfo)
{
	/* have some default contrast/backlight settings */
	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);

	if (sinfo->lcdcon_is_backlight)
		init_backlight(sinfo);
}


static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = {
	.type		= FB_TYPE_PACKED_PIXELS,
	.visual		= FB_VISUAL_TRUECOLOR,
	.xpanstep	= 0,
	.ypanstep	= 1,
	.ywrapstep	= 0,
	.accel		= FB_ACCEL_NONE,
};
{'fraction_non_alphanumeric': 0.10874948411060668, 'fraction_numerical': 0.012484523318200578, 'mean_word_length': 5.241468126207341, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 101, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6510261', 'n_tokens_mistral': 4329, 'n_tokens_neox': 3966, 'n_words': 735}