Revision c1230df7e19e0f27655c0eb9d966c7e03be7cc50 authored by Paulo Zanoni on 03 May 2012, 01:55:43 UTC, committed by Daniel Vetter on 03 May 2012, 13:55:38 UTC
While testing with the intel_infoframes tool on gen4, I see that when video DIP is disabled, what we write to the DATA memory is not exactly what we read back later. This regression has been introduce in commit 64a8fc0145a1d0fdc25fc9367c2e6c621955fb3b Author: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Thu Sep 22 11:16:00 2011 +0530 drm/i915: fix ILK+ infoframe support That commit was setting VIDEO_DIP_CTL to 0 when initializing, which caused the problem. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=43947 Cc: stable@kernel.org Tested-by: Yang Guang <guang.a.yang@intel.com> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Reviewed-by: Eugeni Dodonov <eugeni.dodonov@intel.com> [danvet: Pimped commit message by using the usual commit citation layout.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
1 parent 6200497
bf54x-lq043fb.c
/*
* File: drivers/video/bf54x-lq043.c
* Based on:
* Author: Michael Hennerich <hennerich@blackfin.uclinux.org>
*
* Created:
* Description: ADSP-BF54x Framebuffer driver
*
*
* Modified:
* Copyright 2007-2008 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see the file COPYING, or write
* to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/device.h>
#include <linux/backlight.h>
#include <linux/lcd.h>
#include <linux/spinlock.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <asm/blackfin.h>
#include <asm/irq.h>
#include <asm/dpmc.h>
#include <asm/dma-mapping.h>
#include <asm/dma.h>
#include <asm/gpio.h>
#include <asm/portmux.h>
#include <mach/bf54x-lq043.h>
#define NO_BL_SUPPORT
#define DRIVER_NAME "bf54x-lq043"
static char driver_name[] = DRIVER_NAME;
#define BFIN_LCD_NBR_PALETTE_ENTRIES 256
#define EPPI0_18 {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, \
P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, \
P_PPI0_D11, P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, P_PPI0_D16, P_PPI0_D17, 0}
#define EPPI0_24 {P_PPI0_D18, P_PPI0_D19, P_PPI0_D20, P_PPI0_D21, P_PPI0_D22, P_PPI0_D23, 0}
struct bfin_bf54xfb_info {
struct fb_info *fb;
struct device *dev;
struct bfin_bf54xfb_mach_info *mach_info;
unsigned char *fb_buffer; /* RGB Buffer */
dma_addr_t dma_handle;
int lq043_open_cnt;
int irq;
spinlock_t lock; /* lock */
};
static int nocursor;
module_param(nocursor, int, 0644);
MODULE_PARM_DESC(nocursor, "cursor enable/disable");
static int outp_rgb666;
module_param(outp_rgb666, int, 0);
MODULE_PARM_DESC(outp_rgb666, "Output 18-bit RGB666");
#define LCD_X_RES 480 /*Horizontal Resolution */
#define LCD_Y_RES 272 /* Vertical Resolution */
#define LCD_BPP 24 /* Bit Per Pixel */
#define DMA_BUS_SIZE 32
/* -- Horizontal synchronizing --
*
* Timing characteristics taken from the SHARP LQ043T1DG01 datasheet
* (LCY-W-06602A Page 9 of 22)
*
* Clock Frequency 1/Tc Min 7.83 Typ 9.00 Max 9.26 MHz
*
* Period TH - 525 - Clock
* Pulse width THp - 41 - Clock
* Horizontal period THd - 480 - Clock
* Back porch THb - 2 - Clock
* Front porch THf - 2 - Clock
*
* -- Vertical synchronizing --
* Period TV - 286 - Line
* Pulse width TVp - 10 - Line
* Vertical period TVd - 272 - Line
* Back porch TVb - 2 - Line
* Front porch TVf - 2 - Line
*/
#define LCD_CLK (8*1000*1000) /* 8MHz */
/* # active data to transfer after Horizontal Delay clock */
#define EPPI_HCOUNT LCD_X_RES
/* # active lines to transfer after Vertical Delay clock */
#define EPPI_VCOUNT LCD_Y_RES
/* Samples per Line = 480 (active data) + 45 (padding) */
#define EPPI_LINE 525
/* Lines per Frame = 272 (active data) + 14 (padding) */
#define EPPI_FRAME 286
/* FS1 (Hsync) Width (Typical)*/
#define EPPI_FS1W_HBL 41
/* FS1 (Hsync) Period (Typical) */
#define EPPI_FS1P_AVPL EPPI_LINE
/* Horizontal Delay clock after assertion of Hsync (Typical) */
#define EPPI_HDELAY 43
/* FS2 (Vsync) Width = FS1 (Hsync) Period * 10 */
#define EPPI_FS2W_LVB (EPPI_LINE * 10)
/* FS2 (Vsync) Period = FS1 (Hsync) Period * Lines per Frame */
#define EPPI_FS2P_LAVF (EPPI_LINE * EPPI_FRAME)
/* Vertical Delay after assertion of Vsync (2 Lines) */
#define EPPI_VDELAY 12
#define EPPI_CLIP 0xFF00FF00
/* EPPI Control register configuration value for RGB out
* - EPPI as Output
* GP 2 frame sync mode,
* Internal Clock generation disabled, Internal FS generation enabled,
* Receives samples on EPPI_CLK raising edge, Transmits samples on EPPI_CLK falling edge,
* FS1 & FS2 are active high,
* DLEN = 6 (24 bits for RGB888 out) or 5 (18 bits for RGB666 out)
* DMA Unpacking disabled when RGB Formating is enabled, otherwise DMA unpacking enabled
* Swapping Enabled,
* One (DMA) Channel Mode,
* RGB Formatting Enabled for RGB666 output, disabled for RGB888 output
* Regular watermark - when FIFO is 100% full,
* Urgent watermark - when FIFO is 75% full
*/
#define EPPI_CONTROL (0x20136E2E | SWAPEN)
static inline u16 get_eppi_clkdiv(u32 target_ppi_clk)
{
u32 sclk = get_sclk();
/* EPPI_CLK = (SCLK) / (2 * (EPPI_CLKDIV[15:0] + 1)) */
return (((sclk / target_ppi_clk) / 2) - 1);
}
static void config_ppi(struct bfin_bf54xfb_info *fbi)
{
u16 eppi_clkdiv = get_eppi_clkdiv(LCD_CLK);
bfin_write_EPPI0_FS1W_HBL(EPPI_FS1W_HBL);
bfin_write_EPPI0_FS1P_AVPL(EPPI_FS1P_AVPL);
bfin_write_EPPI0_FS2W_LVB(EPPI_FS2W_LVB);
bfin_write_EPPI0_FS2P_LAVF(EPPI_FS2P_LAVF);
bfin_write_EPPI0_CLIP(EPPI_CLIP);
bfin_write_EPPI0_FRAME(EPPI_FRAME);
bfin_write_EPPI0_LINE(EPPI_LINE);
bfin_write_EPPI0_HCOUNT(EPPI_HCOUNT);
bfin_write_EPPI0_HDELAY(EPPI_HDELAY);
bfin_write_EPPI0_VCOUNT(EPPI_VCOUNT);
bfin_write_EPPI0_VDELAY(EPPI_VDELAY);
bfin_write_EPPI0_CLKDIV(eppi_clkdiv);
/*
* DLEN = 6 (24 bits for RGB888 out) or 5 (18 bits for RGB666 out)
* RGB Formatting Enabled for RGB666 output, disabled for RGB888 output
*/
if (outp_rgb666)
bfin_write_EPPI0_CONTROL((EPPI_CONTROL & ~DLENGTH) | DLEN_18 |
RGB_FMT_EN);
else
bfin_write_EPPI0_CONTROL(((EPPI_CONTROL & ~DLENGTH) | DLEN_24) &
~RGB_FMT_EN);
}
static int config_dma(struct bfin_bf54xfb_info *fbi)
{
set_dma_config(CH_EPPI0,
set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO,
INTR_DISABLE, DIMENSION_2D,
DATA_SIZE_32,
DMA_NOSYNC_KEEP_DMA_BUF));
set_dma_x_count(CH_EPPI0, (LCD_X_RES * LCD_BPP) / DMA_BUS_SIZE);
set_dma_x_modify(CH_EPPI0, DMA_BUS_SIZE / 8);
set_dma_y_count(CH_EPPI0, LCD_Y_RES);
set_dma_y_modify(CH_EPPI0, DMA_BUS_SIZE / 8);
set_dma_start_addr(CH_EPPI0, (unsigned long)fbi->fb_buffer);
return 0;
}
static int request_ports(struct bfin_bf54xfb_info *fbi)
{
u16 eppi_req_18[] = EPPI0_18;
u16 disp = fbi->mach_info->disp;
if (gpio_request_one(disp, GPIOF_OUT_INIT_HIGH, DRIVER_NAME)) {
printk(KERN_ERR "Requesting GPIO %d failed\n", disp);
return -EFAULT;
}
if (peripheral_request_list(eppi_req_18, DRIVER_NAME)) {
printk(KERN_ERR "Requesting Peripherals failed\n");
gpio_free(disp);
return -EFAULT;
}
if (!outp_rgb666) {
u16 eppi_req_24[] = EPPI0_24;
if (peripheral_request_list(eppi_req_24, DRIVER_NAME)) {
printk(KERN_ERR "Requesting Peripherals failed\n");
peripheral_free_list(eppi_req_18);
gpio_free(disp);
return -EFAULT;
}
}
return 0;
}
static void free_ports(struct bfin_bf54xfb_info *fbi)
{
u16 eppi_req_18[] = EPPI0_18;
gpio_free(fbi->mach_info->disp);
peripheral_free_list(eppi_req_18);
if (!outp_rgb666) {
u16 eppi_req_24[] = EPPI0_24;
peripheral_free_list(eppi_req_24);
}
}
static int bfin_bf54x_fb_open(struct fb_info *info, int user)
{
struct bfin_bf54xfb_info *fbi = info->par;
spin_lock(&fbi->lock);
fbi->lq043_open_cnt++;
if (fbi->lq043_open_cnt <= 1) {
bfin_write_EPPI0_CONTROL(0);
SSYNC();
config_dma(fbi);
config_ppi(fbi);
/* start dma */
enable_dma(CH_EPPI0);
bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN);
}
spin_unlock(&fbi->lock);
return 0;
}
static int bfin_bf54x_fb_release(struct fb_info *info, int user)
{
struct bfin_bf54xfb_info *fbi = info->par;
spin_lock(&fbi->lock);
fbi->lq043_open_cnt--;
if (fbi->lq043_open_cnt <= 0) {
bfin_write_EPPI0_CONTROL(0);
SSYNC();
disable_dma(CH_EPPI0);
}
spin_unlock(&fbi->lock);
return 0;
}
static int bfin_bf54x_fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
switch (var->bits_per_pixel) {
case 24:/* TRUECOLOUR, 16m */
var->red.offset = 16;
var->green.offset = 8;
var->blue.offset = 0;
var->red.length = var->green.length = var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
var->transp.msb_right = 0;
var->red.msb_right = 0;
var->green.msb_right = 0;
var->blue.msb_right = 0;
break;
default:
pr_debug("%s: depth not supported: %u BPP\n", __func__,
var->bits_per_pixel);
return -EINVAL;
}
if (info->var.xres != var->xres || info->var.yres != var->yres ||
info->var.xres_virtual != var->xres_virtual ||
info->var.yres_virtual != var->yres_virtual) {
pr_debug("%s: Resolution not supported: X%u x Y%u \n",
__func__, var->xres, var->yres);
return -EINVAL;
}
/*
* Memory limit
*/
if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
__func__, var->yres_virtual);
return -ENOMEM;
}
return 0;
}
int bfin_bf54x_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
if (nocursor)
return 0;
else
return -EINVAL; /* just to force soft_cursor() call */
}
static int bfin_bf54x_fb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp,
struct fb_info *info)
{
if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
return -EINVAL;
if (info->var.grayscale) {
/* grayscale = 0.30*R + 0.59*G + 0.11*B */
red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
}
if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
u32 value;
/* Place color in the pseudopalette */
if (regno > 16)
return -EINVAL;
red >>= (16 - info->var.red.length);
green >>= (16 - info->var.green.length);
blue >>= (16 - info->var.blue.length);
value = (red << info->var.red.offset) |
(green << info->var.green.offset) |
(blue << info->var.blue.offset);
value &= 0xFFFFFF;
((u32 *) (info->pseudo_palette))[regno] = value;
}
return 0;
}
static struct fb_ops bfin_bf54x_fb_ops = {
.owner = THIS_MODULE,
.fb_open = bfin_bf54x_fb_open,
.fb_release = bfin_bf54x_fb_release,
.fb_check_var = bfin_bf54x_fb_check_var,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_cursor = bfin_bf54x_fb_cursor,
.fb_setcolreg = bfin_bf54x_fb_setcolreg,
};
#ifndef NO_BL_SUPPORT
static int bl_get_brightness(struct backlight_device *bd)
{
return 0;
}
static const struct backlight_ops bfin_lq043fb_bl_ops = {
.get_brightness = bl_get_brightness,
};
static struct backlight_device *bl_dev;
static int bfin_lcd_get_power(struct lcd_device *dev)
{
return 0;
}
static int bfin_lcd_set_power(struct lcd_device *dev, int power)
{
return 0;
}
static int bfin_lcd_get_contrast(struct lcd_device *dev)
{
return 0;
}
static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
{
return 0;
}
static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi)
{
if (!fi || (fi == &bfin_bf54x_fb))
return 1;
return 0;
}
static struct lcd_ops bfin_lcd_ops = {
.get_power = bfin_lcd_get_power,
.set_power = bfin_lcd_set_power,
.get_contrast = bfin_lcd_get_contrast,
.set_contrast = bfin_lcd_set_contrast,
.check_fb = bfin_lcd_check_fb,
};
static struct lcd_device *lcd_dev;
#endif
static irqreturn_t bfin_bf54x_irq_error(int irq, void *dev_id)
{
/*struct bfin_bf54xfb_info *info = dev_id;*/
u16 status = bfin_read_EPPI0_STATUS();
bfin_write_EPPI0_STATUS(0xFFFF);
if (status) {
bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN);
disable_dma(CH_EPPI0);
/* start dma */
enable_dma(CH_EPPI0);
bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN);
bfin_write_EPPI0_STATUS(0xFFFF);
}
return IRQ_HANDLED;
}
static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
{
#ifndef NO_BL_SUPPORT
struct backlight_properties props;
#endif
struct bfin_bf54xfb_info *info;
struct fb_info *fbinfo;
int ret;
printk(KERN_INFO DRIVER_NAME ": FrameBuffer initializing...\n");
if (request_dma(CH_EPPI0, "CH_EPPI0") < 0) {
printk(KERN_ERR DRIVER_NAME
": couldn't request CH_EPPI0 DMA\n");
ret = -EFAULT;
goto out1;
}
fbinfo =
framebuffer_alloc(sizeof(struct bfin_bf54xfb_info), &pdev->dev);
if (!fbinfo) {
ret = -ENOMEM;
goto out2;
}
info = fbinfo->par;
info->fb = fbinfo;
info->dev = &pdev->dev;
platform_set_drvdata(pdev, fbinfo);
strcpy(fbinfo->fix.id, driver_name);
info->mach_info = pdev->dev.platform_data;
if (info->mach_info == NULL) {
dev_err(&pdev->dev,
"no platform data for lcd, cannot attach\n");
ret = -EINVAL;
goto out3;
}
fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
fbinfo->fix.type_aux = 0;
fbinfo->fix.xpanstep = 0;
fbinfo->fix.ypanstep = 0;
fbinfo->fix.ywrapstep = 0;
fbinfo->fix.accel = FB_ACCEL_NONE;
fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
fbinfo->var.nonstd = 0;
fbinfo->var.activate = FB_ACTIVATE_NOW;
fbinfo->var.height = info->mach_info->height;
fbinfo->var.width = info->mach_info->width;
fbinfo->var.accel_flags = 0;
fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
fbinfo->fbops = &bfin_bf54x_fb_ops;
fbinfo->flags = FBINFO_FLAG_DEFAULT;
fbinfo->var.xres = info->mach_info->xres.defval;
fbinfo->var.xres_virtual = info->mach_info->xres.defval;
fbinfo->var.yres = info->mach_info->yres.defval;
fbinfo->var.yres_virtual = info->mach_info->yres.defval;
fbinfo->var.bits_per_pixel = info->mach_info->bpp.defval;
fbinfo->var.upper_margin = 0;
fbinfo->var.lower_margin = 0;
fbinfo->var.vsync_len = 0;
fbinfo->var.left_margin = 0;
fbinfo->var.right_margin = 0;
fbinfo->var.hsync_len = 0;
fbinfo->var.red.offset = 16;
fbinfo->var.green.offset = 8;
fbinfo->var.blue.offset = 0;
fbinfo->var.transp.offset = 0;
fbinfo->var.red.length = 8;
fbinfo->var.green.length = 8;
fbinfo->var.blue.length = 8;
fbinfo->var.transp.length = 0;
fbinfo->fix.smem_len = info->mach_info->xres.max *
info->mach_info->yres.max * info->mach_info->bpp.max / 8;
fbinfo->fix.line_length = fbinfo->var.xres_virtual *
fbinfo->var.bits_per_pixel / 8;
info->fb_buffer =
dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle,
GFP_KERNEL);
if (NULL == info->fb_buffer) {
printk(KERN_ERR DRIVER_NAME
": couldn't allocate dma buffer.\n");
ret = -ENOMEM;
goto out3;
}
fbinfo->screen_base = (void *)info->fb_buffer;
fbinfo->fix.smem_start = (int)info->fb_buffer;
fbinfo->fbops = &bfin_bf54x_fb_ops;
fbinfo->pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL);
if (!fbinfo->pseudo_palette) {
printk(KERN_ERR DRIVER_NAME
"Fail to allocate pseudo_palette\n");
ret = -ENOMEM;
goto out4;
}
if (fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0)
< 0) {
printk(KERN_ERR DRIVER_NAME
"Fail to allocate colormap (%d entries)\n",
BFIN_LCD_NBR_PALETTE_ENTRIES);
ret = -EFAULT;
goto out5;
}
if (request_ports(info)) {
printk(KERN_ERR DRIVER_NAME ": couldn't request gpio port.\n");
ret = -EFAULT;
goto out6;
}
info->irq = platform_get_irq(pdev, 0);
if (info->irq < 0) {
ret = -EINVAL;
goto out7;
}
if (request_irq(info->irq, bfin_bf54x_irq_error, 0,
"PPI ERROR", info) < 0) {
printk(KERN_ERR DRIVER_NAME
": unable to request PPI ERROR IRQ\n");
ret = -EFAULT;
goto out7;
}
if (register_framebuffer(fbinfo) < 0) {
printk(KERN_ERR DRIVER_NAME
": unable to register framebuffer.\n");
ret = -EINVAL;
goto out8;
}
#ifndef NO_BL_SUPPORT
memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_RAW;
props.max_brightness = 255;
bl_dev = backlight_device_register("bf54x-bl", NULL, NULL,
&bfin_lq043fb_bl_ops, &props);
if (IS_ERR(bl_dev)) {
printk(KERN_ERR DRIVER_NAME
": unable to register backlight.\n");
ret = -EINVAL;
unregister_framebuffer(fbinfo);
goto out8;
}
lcd_dev = lcd_device_register(DRIVER_NAME, &pdev->dev, NULL, &bfin_lcd_ops);
lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n");
#endif
return 0;
out8:
free_irq(info->irq, info);
out7:
free_ports(info);
out6:
fb_dealloc_cmap(&fbinfo->cmap);
out5:
kfree(fbinfo->pseudo_palette);
out4:
dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
info->dma_handle);
out3:
framebuffer_release(fbinfo);
out2:
free_dma(CH_EPPI0);
out1:
platform_set_drvdata(pdev, NULL);
return ret;
}
static int __devexit bfin_bf54x_remove(struct platform_device *pdev)
{
struct fb_info *fbinfo = platform_get_drvdata(pdev);
struct bfin_bf54xfb_info *info = fbinfo->par;
free_dma(CH_EPPI0);
free_irq(info->irq, info);
if (info->fb_buffer != NULL)
dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
info->dma_handle);
kfree(fbinfo->pseudo_palette);
fb_dealloc_cmap(&fbinfo->cmap);
#ifndef NO_BL_SUPPORT
lcd_device_unregister(lcd_dev);
backlight_device_unregister(bl_dev);
#endif
unregister_framebuffer(fbinfo);
free_ports(info);
printk(KERN_INFO DRIVER_NAME ": Unregister LCD driver.\n");
return 0;
}
#ifdef CONFIG_PM
static int bfin_bf54x_suspend(struct platform_device *pdev, pm_message_t state)
{
struct fb_info *fbinfo = platform_get_drvdata(pdev);
bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN);
disable_dma(CH_EPPI0);
bfin_write_EPPI0_STATUS(0xFFFF);
return 0;
}
static int bfin_bf54x_resume(struct platform_device *pdev)
{
struct fb_info *fbinfo = platform_get_drvdata(pdev);
struct bfin_bf54xfb_info *info = fbinfo->par;
if (info->lq043_open_cnt) {
bfin_write_EPPI0_CONTROL(0);
SSYNC();
config_dma(info);
config_ppi(info);
/* start dma */
enable_dma(CH_EPPI0);
bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN);
}
return 0;
}
#else
#define bfin_bf54x_suspend NULL
#define bfin_bf54x_resume NULL
#endif
static struct platform_driver bfin_bf54x_driver = {
.probe = bfin_bf54x_probe,
.remove = __devexit_p(bfin_bf54x_remove),
.suspend = bfin_bf54x_suspend,
.resume = bfin_bf54x_resume,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
};
static int __init bfin_bf54x_driver_init(void)
{
return platform_driver_register(&bfin_bf54x_driver);
}
static void __exit bfin_bf54x_driver_cleanup(void)
{
platform_driver_unregister(&bfin_bf54x_driver);
}
MODULE_DESCRIPTION("Blackfin BF54x TFT LCD Driver");
MODULE_LICENSE("GPL");
module_init(bfin_bf54x_driver_init);
module_exit(bfin_bf54x_driver_cleanup);
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...