aboutsummaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig17
-rw-r--r--drivers/video/aty/radeon_base.c4
-rw-r--r--drivers/video/cobalt_lcdfb.c2
-rw-r--r--drivers/video/efifb.c11
-rw-r--r--drivers/video/fbmem.c77
-rw-r--r--drivers/video/fbsysfs.c1
-rw-r--r--drivers/video/mx3fb.c3
-rw-r--r--drivers/video/offb.c28
-rw-r--r--drivers/video/omap2/displays/Kconfig9
-rw-r--r--drivers/video/omap2/displays/Makefile1
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c819
-rw-r--r--drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c78
-rw-r--r--drivers/video/omap2/displays/panel-taal.c143
-rw-r--r--drivers/video/omap2/dss/Kconfig6
-rw-r--r--drivers/video/omap2/dss/Makefile3
-rw-r--r--drivers/video/omap2/dss/core.c85
-rw-r--r--drivers/video/omap2/dss/display.c9
-rw-r--r--drivers/video/omap2/dss/dss.c24
-rw-r--r--drivers/video/omap2/dss/dss.h50
-rw-r--r--drivers/video/omap2/dss/manager.c21
-rw-r--r--drivers/video/omap2/dss/sdi.c26
-rw-r--r--drivers/video/omap2/dss/venc.c15
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c5
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c25
-rw-r--r--drivers/video/vesafb.c11
-rw-r--r--drivers/video/vga16fb.c26
-rw-r--r--drivers/video/via/Makefile4
-rw-r--r--drivers/video/via/accel.c137
-rw-r--r--drivers/video/via/accel.h40
-rw-r--r--drivers/video/via/chip.h8
-rw-r--r--drivers/video/via/dvi.c37
-rw-r--r--drivers/video/via/global.h1
-rw-r--r--drivers/video/via/hw.c307
-rw-r--r--drivers/video/via/hw.h20
-rw-r--r--drivers/video/via/ioctl.h2
-rw-r--r--drivers/video/via/lcd.c31
-rw-r--r--drivers/video/via/lcd.h2
-rw-r--r--drivers/video/via/share.h20
-rw-r--r--drivers/video/via/via-core.c668
-rw-r--r--drivers/video/via/via-gpio.c285
-rw-r--r--drivers/video/via/via_i2c.c232
-rw-r--r--drivers/video/via/via_modesetting.c126
-rw-r--r--drivers/video/via/via_modesetting.h (renamed from drivers/video/via/via_i2c.h)42
-rw-r--r--drivers/video/via/via_utility.c1
-rw-r--r--drivers/video/via/viafbdev.c181
-rw-r--r--drivers/video/via/viafbdev.h14
-rw-r--r--drivers/video/via/viamode.c15
-rw-r--r--drivers/video/via/vt1636.c34
-rw-r--r--drivers/video/via/vt1636.h2
49 files changed, 2977 insertions, 731 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 773c4a68de8..3dc10381e0c 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1511,6 +1511,7 @@ config FB_VIA
select FB_CFB_IMAGEBLIT
select I2C_ALGOBIT
select I2C
+ select GPIOLIB
help
This is the frame buffer device driver for Graphics chips of VIA
UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/
@@ -1520,6 +1521,21 @@ config FB_VIA
To compile this driver as a module, choose M here: the
module will be called viafb.
+
+if FB_VIA
+
+config FB_VIA_DIRECT_PROCFS
+ bool "direct hardware access via procfs (DEPRECATED)(DANGEROUS)"
+ depends on FB_VIA
+ default n
+ help
+ Allow direct hardware access to some output registers via procfs.
+ This is dangerous but may provide the only chance to get the
+ correct output device configuration.
+ Its use is strongly discouraged.
+
+endif
+
config FB_NEOMAGIC
tristate "NeoMagic display support"
depends on FB && PCI
@@ -2194,7 +2210,6 @@ config FB_MSM
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- default y
config FB_MX3
tristate "MX3 Framebuffer support"
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 6c37e8ee5ef..3c1e13ed1cb 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -2099,7 +2099,7 @@ static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u
}
-static ssize_t radeon_show_edid1(struct kobject *kobj,
+static ssize_t radeon_show_edid1(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
@@ -2112,7 +2112,7 @@ static ssize_t radeon_show_edid1(struct kobject *kobj,
}
-static ssize_t radeon_show_edid2(struct kobject *kobj,
+static ssize_t radeon_show_edid2(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c
index 5eb61b5adfe..42fe155aba0 100644
--- a/drivers/video/cobalt_lcdfb.c
+++ b/drivers/video/cobalt_lcdfb.c
@@ -123,7 +123,7 @@ static void lcd_clear(struct fb_info *info)
lcd_write_control(info, LCD_RESET);
}
-static struct fb_fix_screeninfo cobalt_lcdfb_fix __initdata = {
+static struct fb_fix_screeninfo cobalt_lcdfb_fix __devinitdata = {
.id = "cobalt-lcd",
.type = FB_TYPE_TEXT,
.type_aux = FB_AUX_TEXT_MDA,
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
index ecf405562f5..4a56f46af40 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/efifb.c
@@ -168,7 +168,7 @@ static void efifb_destroy(struct fb_info *info)
{
if (info->screen_base)
iounmap(info->screen_base);
- release_mem_region(info->aperture_base, info->aperture_size);
+ release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
framebuffer_release(info);
}
@@ -292,8 +292,13 @@ static int __devinit efifb_probe(struct platform_device *dev)
info->pseudo_palette = info->par;
info->par = NULL;
- info->aperture_base = efifb_fix.smem_start;
- info->aperture_size = size_remap;
+ info->apertures = alloc_apertures(1);
+ if (!info->apertures) {
+ err = -ENOMEM;
+ goto err_release_fb;
+ }
+ info->apertures->ranges[0].base = efifb_fix.smem_start;
+ info->apertures->ranges[0].size = size_remap;
info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len);
if (!info->screen_base) {
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index a15b44e9c00..731fce64df9 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1468,16 +1468,70 @@ static int fb_check_foreignness(struct fb_info *fi)
return 0;
}
-static bool fb_do_apertures_overlap(struct fb_info *gen, struct fb_info *hw)
+static bool apertures_overlap(struct aperture *gen, struct aperture *hw)
{
/* is the generic aperture base the same as the HW one */
- if (gen->aperture_base == hw->aperture_base)
+ if (gen->base == hw->base)
return true;
/* is the generic aperture base inside the hw base->hw base+size */
- if (gen->aperture_base > hw->aperture_base && gen->aperture_base <= hw->aperture_base + hw->aperture_size)
+ if (gen->base > hw->base && gen->base <= hw->base + hw->size)
return true;
return false;
}
+
+static bool fb_do_apertures_overlap(struct apertures_struct *gena,
+ struct apertures_struct *hwa)
+{
+ int i, j;
+ if (!hwa || !gena)
+ return false;
+
+ for (i = 0; i < hwa->count; ++i) {
+ struct aperture *h = &hwa->ranges[i];
+ for (j = 0; j < gena->count; ++j) {
+ struct aperture *g = &gena->ranges[j];
+ printk(KERN_DEBUG "checking generic (%llx %llx) vs hw (%llx %llx)\n",
+ (unsigned long long)g->base,
+ (unsigned long long)g->size,
+ (unsigned long long)h->base,
+ (unsigned long long)h->size);
+ if (apertures_overlap(g, h))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+#define VGA_FB_PHYS 0xA0000
+void remove_conflicting_framebuffers(struct apertures_struct *a,
+ const char *name, bool primary)
+{
+ int i;
+
+ /* check all firmware fbs and kick off if the base addr overlaps */
+ for (i = 0 ; i < FB_MAX; i++) {
+ struct apertures_struct *gen_aper;
+ if (!registered_fb[i])
+ continue;
+
+ if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
+ continue;
+
+ gen_aper = registered_fb[i]->apertures;
+ if (fb_do_apertures_overlap(gen_aper, a) ||
+ (primary && gen_aper && gen_aper->count &&
+ gen_aper->ranges[0].base == VGA_FB_PHYS)) {
+
+ printk(KERN_ERR "fb: conflicting fb hw usage "
+ "%s vs %s - removing generic driver\n",
+ name, registered_fb[i]->fix.id);
+ unregister_framebuffer(registered_fb[i]);
+ }
+ }
+}
+EXPORT_SYMBOL(remove_conflicting_framebuffers);
+
/**
* register_framebuffer - registers a frame buffer device
* @fb_info: frame buffer info structure
@@ -1501,21 +1555,8 @@ register_framebuffer(struct fb_info *fb_info)
if (fb_check_foreignness(fb_info))
return -ENOSYS;
- /* check all firmware fbs and kick off if the base addr overlaps */
- for (i = 0 ; i < FB_MAX; i++) {
- if (!registered_fb[i])
- continue;
-
- if (registered_fb[i]->flags & FBINFO_MISC_FIRMWARE) {
- if (fb_do_apertures_overlap(registered_fb[i], fb_info)) {
- printk(KERN_ERR "fb: conflicting fb hw usage "
- "%s vs %s - removing generic driver\n",
- fb_info->fix.id,
- registered_fb[i]->fix.id);
- unregister_framebuffer(registered_fb[i]);
- }
- }
- }
+ remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id,
+ fb_is_primary_device(fb_info));
num_registered_fb++;
for (i = 0 ; i < FB_MAX; i++)
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 81aa3129c17..0a08f134122 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -80,6 +80,7 @@ EXPORT_SYMBOL(framebuffer_alloc);
*/
void framebuffer_release(struct fb_info *info)
{
+ kfree(info->apertures);
kfree(info);
}
EXPORT_SYMBOL(framebuffer_release);
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index 772ba3f45e6..7cfc170bce1 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -387,7 +387,8 @@ static void sdc_disable_channel(struct mx3fb_info *mx3_fbi)
spin_unlock_irqrestore(&mx3fb->lock, flags);
- mx3_fbi->txd->chan->device->device_terminate_all(mx3_fbi->txd->chan);
+ mx3_fbi->txd->chan->device->device_control(mx3_fbi->txd->chan,
+ DMA_TERMINATE_ALL, 0);
mx3_fbi->txd = NULL;
mx3_fbi->cookie = -EINVAL;
}
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index 61f8b8f919b..46dda7d8aae 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -285,7 +285,7 @@ static void offb_destroy(struct fb_info *info)
{
if (info->screen_base)
iounmap(info->screen_base);
- release_mem_region(info->aperture_base, info->aperture_size);
+ release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
framebuffer_release(info);
}
@@ -491,8 +491,11 @@ static void __init offb_init_fb(const char *name, const char *full_name,
var->vmode = FB_VMODE_NONINTERLACED;
/* set offb aperture size for generic probing */
- info->aperture_base = address;
- info->aperture_size = fix->smem_len;
+ info->apertures = alloc_apertures(1);
+ if (!info->apertures)
+ goto out_aper;
+ info->apertures->ranges[0].base = address;
+ info->apertures->ranges[0].size = fix->smem_len;
info->fbops = &offb_ops;
info->screen_base = ioremap(address, fix->smem_len);
@@ -501,17 +504,20 @@ static void __init offb_init_fb(const char *name, const char *full_name,
fb_alloc_cmap(&info->cmap, 256, 0);
- if (register_framebuffer(info) < 0) {
- iounmap(par->cmap_adr);
- par->cmap_adr = NULL;
- iounmap(info->screen_base);
- framebuffer_release(info);
- release_mem_region(res_start, res_size);
- return;
- }
+ if (register_framebuffer(info) < 0)
+ goto out_err;
printk(KERN_INFO "fb%d: Open Firmware frame buffer device on %s\n",
info->node, full_name);
+ return;
+
+out_err:
+ iounmap(info->screen_base);
+out_aper:
+ iounmap(par->cmap_adr);
+ par->cmap_adr = NULL;
+ framebuffer_release(info);
+ release_mem_region(res_start, res_size);
}
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index dfb57ee5086..881c9f77c75 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -10,6 +10,7 @@ config PANEL_GENERIC
config PANEL_SHARP_LS037V7DW01
tristate "Sharp LS037V7DW01 LCD Panel"
depends on OMAP2_DSS
+ select BACKLIGHT_CLASS_DEVICE
help
LCD Panel used in TI's SDP3430 and EVM boards
@@ -33,8 +34,14 @@ config PANEL_TOPPOLY_TDO35S
config PANEL_TPO_TD043MTEA1
tristate "TPO TD043MTEA1 LCD Panel"
- depends on OMAP2_DSS && I2C
+ depends on OMAP2_DSS && SPI
help
LCD Panel used in OMAP3 Pandora
+config PANEL_ACX565AKM
+ tristate "ACX565AKM Panel"
+ depends on OMAP2_DSS_SDI
+ select BACKLIGHT_CLASS_DEVICE
+ help
+ This is the LCD panel used on Nokia N900
endmenu
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
index e2bb32168de..aa386095d7c 100644
--- a/drivers/video/omap2/displays/Makefile
+++ b/drivers/video/omap2/displays/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_PANEL_SHARP_LQ043T1DG01) += panel-sharp-lq043t1dg01.o
obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
obj-$(CONFIG_PANEL_TOPPOLY_TDO35S) += panel-toppoly-tdo35s.o
obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
+obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
new file mode 100644
index 00000000000..1f8eb70e293
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -0,0 +1,819 @@
+/*
+ * Support for ACX565AKM LCD Panel used on Nokia N900
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * Original Driver Author: Imre Deak <imre.deak@nokia.com>
+ * Based on panel-generic.c by Tomi Valkeinen <tomi.valkeinen@nokia.com>
+ * Adapted to new DSS2 framework: Roger Quadros <roger.quadros@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
+
+#include <plat/display.h>
+
+#define MIPID_CMD_READ_DISP_ID 0x04
+#define MIPID_CMD_READ_RED 0x06
+#define MIPID_CMD_READ_GREEN 0x07
+#define MIPID_CMD_READ_BLUE 0x08
+#define MIPID_CMD_READ_DISP_STATUS 0x09
+#define MIPID_CMD_RDDSDR 0x0F
+#define MIPID_CMD_SLEEP_IN 0x10
+#define MIPID_CMD_SLEEP_OUT 0x11
+#define MIPID_CMD_DISP_OFF 0x28
+#define MIPID_CMD_DISP_ON 0x29
+#define MIPID_CMD_WRITE_DISP_BRIGHTNESS 0x51
+#define MIPID_CMD_READ_DISP_BRIGHTNESS 0x52
+#define MIPID_CMD_WRITE_CTRL_DISP 0x53
+
+#define CTRL_DISP_BRIGHTNESS_CTRL_ON (1 << 5)
+#define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON (1 << 4)
+#define CTRL_DISP_BACKLIGHT_ON (1 << 2)
+#define CTRL_DISP_AUTO_BRIGHTNESS_ON (1 << 1)
+
+#define MIPID_CMD_READ_CTRL_DISP 0x54
+#define MIPID_CMD_WRITE_CABC 0x55
+#define MIPID_CMD_READ_CABC 0x56
+
+#define MIPID_VER_LPH8923 3
+#define MIPID_VER_LS041Y3 4
+#define MIPID_VER_L4F00311 8
+#define MIPID_VER_ACX565AKM 9
+
+struct acx565akm_device {
+ char *name;
+ int enabled;
+ int model;
+ int revision;
+ u8 display_id[3];
+ unsigned has_bc:1;
+ unsigned has_cabc:1;
+ unsigned cabc_mode;
+ unsigned long hw_guard_end; /* next value of jiffies
+ when we can issue the
+ next sleep in/out command */
+ unsigned long hw_guard_wait; /* max guard time in jiffies */
+
+ struct spi_device *spi;
+ struct mutex mutex;
+
+ struct omap_dss_device *dssdev;
+ struct backlight_device *bl_dev;
+};
+
+static struct acx565akm_device acx_dev;
+static int acx565akm_bl_update_status(struct backlight_device *dev);
+
+/*--------------------MIPID interface-----------------------------*/
+
+static void acx565akm_transfer(struct acx565akm_device *md, int cmd,
+ const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+{
+ struct spi_message m;
+ struct spi_transfer *x, xfer[5];
+ int r;
+
+ BUG_ON(md->spi == NULL);
+
+ spi_message_init(&m);
+
+ memset(xfer, 0, sizeof(xfer));
+ x = &xfer[0];
+
+ cmd &= 0xff;
+ x->tx_buf = &cmd;
+ x->bits_per_word = 9;
+ x->len = 2;
+
+ if (rlen > 1 && wlen == 0) {
+ /*
+ * Between the command and the response data there is a
+ * dummy clock cycle. Add an extra bit after the command
+ * word to account for this.
+ */
+ x->bits_per_word = 10;
+ cmd <<= 1;
+ }
+ spi_message_add_tail(x, &m);
+
+ if (wlen) {
+ x++;
+ x->tx_buf = wbuf;
+ x->len = wlen;
+ x->bits_per_word = 9;
+ spi_message_add_tail(x, &m);
+ }
+
+ if (rlen) {
+ x++;
+ x->rx_buf = rbuf;
+ x->len = rlen;
+ spi_message_add_tail(x, &m);
+ }
+
+ r = spi_sync(md->spi, &m);
+ if (r < 0)
+ dev_dbg(&md->spi->dev, "spi_sync %d\n", r);
+}
+
+static inline void acx565akm_cmd(struct acx565akm_device *md, int cmd)
+{
+ acx565akm_transfer(md, cmd, NULL, 0, NULL, 0);
+}
+
+static inline void acx565akm_write(struct acx565akm_device *md,
+ int reg, const u8 *buf, int len)
+{
+ acx565akm_transfer(md, reg, buf, len, NULL, 0);
+}
+
+static inline void acx565akm_read(struct acx565akm_device *md,
+ int reg, u8 *buf, int len)
+{
+ acx565akm_transfer(md, reg, NULL, 0, buf, len);
+}
+
+static void hw_guard_start(struct acx565akm_device *md, int guard_msec)
+{
+ md->hw_guard_wait = msecs_to_jiffies(guard_msec);
+ md->hw_guard_end = jiffies + md->hw_guard_wait;
+}
+
+static void hw_guard_wait(struct acx565akm_device *md)
+{
+ unsigned long wait = md->hw_guard_end - jiffies;
+
+ if ((long)wait > 0 && wait <= md->hw_guard_wait) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(wait);
+ }
+}
+
+/*----------------------MIPID wrappers----------------------------*/
+
+static void set_sleep_mode(struct acx565akm_device *md, int on)
+{
+ int cmd;
+
+ if (on)
+ cmd = MIPID_CMD_SLEEP_IN;
+ else
+ cmd = MIPID_CMD_SLEEP_OUT;
+ /*
+ * We have to keep 120msec between sleep in/out commands.
+ * (8.2.15, 8.2.16).
+ */
+ hw_guard_wait(md);
+ acx565akm_cmd(md, cmd);
+ hw_guard_start(md, 120);
+}
+
+static void set_display_state(struct acx565akm_device *md, int enabled)
+{
+ int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
+
+ acx565akm_cmd(md, cmd);
+}
+
+static int panel_enabled(struct acx565akm_device *md)
+{
+ u32 disp_status;
+ int enabled;
+
+ acx565akm_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
+ disp_status = __be32_to_cpu(disp_status);
+ enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
+ dev_dbg(&md->spi->dev,
+ "LCD panel %senabled by bootloader (status 0x%04x)\n",
+ enabled ? "" : "not ", disp_status);
+ return enabled;
+}
+
+static int panel_detect(struct acx565akm_device *md)
+{
+ acx565akm_read(md, MIPID_CMD_READ_DISP_ID, md->display_id, 3);
+ dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n",
+ md->display_id[0], md->display_id[1], md->display_id[2]);
+
+ switch (md->display_id[0]) {
+ case 0x10:
+ md->model = MIPID_VER_ACX565AKM;
+ md->name = "acx565akm";
+ md->has_bc = 1;
+ md->has_cabc = 1;
+ break;
+ case 0x29:
+ md->model = MIPID_VER_L4F00311;
+ md->name = "l4f00311";
+ break;
+ case 0x45:
+ md->model = MIPID_VER_LPH8923;
+ md->name = "lph8923";
+ break;
+ case 0x83:
+ md->model = MIPID_VER_LS041Y3;
+ md->name = "ls041y3";
+ break;
+ default:
+ md->name = "unknown";
+ dev_err(&md->spi->dev, "invalid display ID\n");
+ return -ENODEV;
+ }
+
+ md->revision = md->display_id[1];
+
+ dev_info(&md->spi->dev, "omapfb: %s rev %02x LCD detected\n",
+ md->name, md->revision);
+
+ return 0;
+}
+
+/*----------------------Backlight Control-------------------------*/
+
+static void enable_backlight_ctrl(struct acx565akm_device *md, int enable)
+{
+ u16 ctrl;
+
+ acx565akm_read(md, MIPID_CMD_READ_CTRL_DISP, (u8 *)&ctrl, 1);
+ if (enable) {
+ ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON |
+ CTRL_DISP_BACKLIGHT_ON;
+ } else {
+ ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON |
+ CTRL_DISP_BACKLIGHT_ON);
+ }
+
+ ctrl |= 1 << 8;
+ acx565akm_write(md, MIPID_CMD_WRITE_CTRL_DISP, (u8 *)&ctrl, 2);
+}
+
+static void set_cabc_mode(struct acx565akm_device *md, unsigned mode)
+{
+ u16 cabc_ctrl;
+
+ md->cabc_mode = mode;
+ if (!md->enabled)
+ return;
+ cabc_ctrl = 0;
+ acx565akm_read(md, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1);
+ cabc_ctrl &= ~3;
+ cabc_ctrl |= (1 << 8) | (mode & 3);
+ acx565akm_write(md, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2);
+}
+
+static unsigned get_cabc_mode(struct acx565akm_device *md)
+{
+ return md->cabc_mode;
+}
+
+static unsigned get_hw_cabc_mode(struct acx565akm_device *md)
+{
+ u8 cabc_ctrl;
+
+ acx565akm_read(md, MIPID_CMD_READ_CABC, &cabc_ctrl, 1);
+ return cabc_ctrl & 3;
+}
+
+static void acx565akm_set_brightness(struct acx565akm_device *md, int level)
+{
+ int bv;
+
+ bv = level | (1 << 8);
+ acx565akm_write(md, MIPID_CMD_WRITE_DISP_BRIGHTNESS, (u8 *)&bv, 2);
+
+ if (level)
+ enable_backlight_ctrl(md, 1);
+ else
+ enable_backlight_ctrl(md, 0);
+}
+
+static int acx565akm_get_actual_brightness(struct acx565akm_device *md)
+{
+ u8 bv;
+
+ acx565akm_read(md, MIPID_CMD_READ_DISP_BRIGHTNESS, &bv, 1);
+
+ return bv;
+}
+
+
+static int acx565akm_bl_update_status(struct backlight_device *dev)
+{
+ struct acx565akm_device *md = dev_get_drvdata(&dev->dev);
+ int r;
+ int level;
+
+ dev_dbg(&md->spi->dev, "%s\n", __func__);
+
+ mutex_lock(&md->mutex);
+
+ if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
+ dev->props.power == FB_BLANK_UNBLANK)
+ level = dev->props.brightness;
+ else
+ level = 0;
+
+ r = 0;
+ if (md->has_bc)
+ acx565akm_set_brightness(md, level);
+ else if (md->dssdev->set_backlight)
+ r = md->dssdev->set_backlight(md->dssdev, level);
+ else
+ r = -ENODEV;
+
+ mutex_unlock(&md->mutex);
+
+ return r;
+}
+
+static int acx565akm_bl_get_intensity(struct backlight_device *dev)
+{
+ struct acx565akm_device *md = dev_get_drvdata(&dev->dev);
+
+ dev_dbg(&dev->dev, "%s\n", __func__);
+
+ if (!md->has_bc && md->dssdev->set_backlight == NULL)
+ return -ENODEV;
+
+ if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
+ dev->props.power == FB_BLANK_UNBLANK) {
+ if (md->has_bc)
+ return acx565akm_get_actual_brightness(md);
+ else
+ return dev->props.brightness;
+ }
+
+ return 0;
+}
+
+static const struct backlight_ops acx565akm_bl_ops = {
+ .get_brightness = acx565akm_bl_get_intensity,
+ .update_status = acx565akm_bl_update_status,
+};
+
+/*--------------------Auto Brightness control via Sysfs---------------------*/
+
+static const char *cabc_modes[] = {
+ "off", /* always used when CABC is not supported */
+ "ui",
+ "still-image",
+ "moving-image",
+};
+
+static ssize_t show_cabc_mode(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct acx565akm_device *md = dev_get_drvdata(dev);
+ const char *mode_str;
+ int mode;
+ int len;
+
+ if (!md->has_cabc)
+ mode = 0;
+ else
+ mode = get_cabc_mode(md);
+ mode_str = "unknown";
+ if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
+ mode_str = cabc_modes[mode];
+ len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
+
+ return len < PAGE_SIZE - 1 ? len :