aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/tc6393xb.c114
-rw-r--r--include/linux/mfd/tc6393xb.h8
2 files changed, 122 insertions, 0 deletions
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index 6197db7d485..f856e9463a9 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -114,6 +114,7 @@ enum {
TC6393XB_CELL_NAND,
TC6393XB_CELL_MMC,
TC6393XB_CELL_OHCI,
+ TC6393XB_CELL_FB,
};
/*--------------------------------------------------------------------------*/
@@ -199,6 +200,29 @@ const static struct resource tc6393xb_ohci_resources[] = {
},
};
+static struct resource __devinitdata tc6393xb_fb_resources[] = {
+ {
+ .start = 0x5000,
+ .end = 0x51ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 0x0500,
+ .end = 0x05ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 0x100000,
+ .end = 0x1fffff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_TC6393_FB,
+ .end = IRQ_TC6393_FB,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
static int tc6393xb_ohci_enable(struct platform_device *dev)
{
struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
@@ -243,6 +267,81 @@ static int tc6393xb_ohci_disable(struct platform_device *dev)
return 0;
}
+static int tc6393xb_fb_enable(struct platform_device *dev)
+{
+ struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
+ unsigned long flags;
+ u16 ccr;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
+ ccr &= ~SCR_CCR_MCLK_MASK;
+ ccr |= SCR_CCR_MCLK_48;
+ tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+ return 0;
+}
+
+static int tc6393xb_fb_disable(struct platform_device *dev)
+{
+ struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
+ unsigned long flags;
+ u16 ccr;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
+ ccr &= ~SCR_CCR_MCLK_MASK;
+ ccr |= SCR_CCR_MCLK_OFF;
+ tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+ return 0;
+}
+
+int tc6393xb_lcd_set_power(struct platform_device *fb, bool on)
+{
+ struct platform_device *dev = to_platform_device(fb->dev.parent);
+ struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+ u8 fer;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ fer = ioread8(tc6393xb->scr + SCR_FER);
+ if (on)
+ fer |= SCR_FER_SLCDEN;
+ else
+ fer &= ~SCR_FER_SLCDEN;
+ iowrite8(fer, tc6393xb->scr + SCR_FER);
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(tc6393xb_lcd_set_power);
+
+int tc6393xb_lcd_mode(struct platform_device *fb,
+ const struct fb_videomode *mode) {
+ struct platform_device *dev = to_platform_device(fb->dev.parent);
+ struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&tc6393xb->lock, flags);
+
+ iowrite16(mode->pixclock, tc6393xb->scr + SCR_PLL1CR + 0);
+ iowrite16(mode->pixclock >> 16, tc6393xb->scr + SCR_PLL1CR + 2);
+
+ spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(tc6393xb_lcd_mode);
+
static struct mfd_cell __devinitdata tc6393xb_cells[] = {
[TC6393XB_CELL_NAND] = {
.name = "tmio-nand",
@@ -264,6 +363,15 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = {
.resume = tc6393xb_ohci_enable,
.disable = tc6393xb_ohci_disable,
},
+ [TC6393XB_CELL_FB] = {
+ .name = "tmio-fb",
+ .num_resources = ARRAY_SIZE(tc6393xb_fb_resources),
+ .resources = tc6393xb_fb_resources,
+ .enable = tc6393xb_fb_enable,
+ .suspend = tc6393xb_fb_disable,
+ .resume = tc6393xb_fb_enable,
+ .disable = tc6393xb_fb_disable,
+ },
};
/*--------------------------------------------------------------------------*/
@@ -547,6 +655,7 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
&tc6393xb_cells[TC6393XB_CELL_NAND];
tc6393xb_cells[TC6393XB_CELL_NAND].data_size =
sizeof(tc6393xb_cells[TC6393XB_CELL_NAND]);
+
tc6393xb_cells[TC6393XB_CELL_MMC].platform_data =
&tc6393xb_cells[TC6393XB_CELL_MMC];
tc6393xb_cells[TC6393XB_CELL_MMC].data_size =
@@ -557,6 +666,11 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
tc6393xb_cells[TC6393XB_CELL_OHCI].data_size =
sizeof(tc6393xb_cells[TC6393XB_CELL_OHCI]);
+ tc6393xb_cells[TC6393XB_CELL_FB].driver_data = tcpd->fb_data;
+ tc6393xb_cells[TC6393XB_CELL_FB].platform_data =
+ &tc6393xb_cells[TC6393XB_CELL_FB];
+ tc6393xb_cells[TC6393XB_CELL_FB].data_size =
+ sizeof(tc6393xb_cells[TC6393XB_CELL_FB]);
ret = mfd_add_devices(&dev->dev, dev->id,
tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
diff --git a/include/linux/mfd/tc6393xb.h b/include/linux/mfd/tc6393xb.h
index 4437736ebe1..626e448205c 100644
--- a/include/linux/mfd/tc6393xb.h
+++ b/include/linux/mfd/tc6393xb.h
@@ -17,6 +17,8 @@
#ifndef MFD_TC6393XB_H
#define MFD_TC6393XB_H
+#include <linux/fb.h>
+
/* Also one should provide the CK3P6MI clock */
struct tc6393xb_platform_data {
u16 scr_pll2cr; /* PLL2 Control */
@@ -33,18 +35,24 @@ struct tc6393xb_platform_data {
void (*teardown)(struct platform_device *dev);
struct tmio_nand_data *nand_data;
+ struct tmio_fb_data *fb_data;
unsigned resume_restore : 1; /* make special actions
to preserve the state
on suspend/resume */
};
+extern int tc6393xb_lcd_mode(struct platform_device *fb,
+ const struct fb_videomode *mode);
+extern int tc6393xb_lcd_set_power(struct platform_device *fb, bool on);
+
/*
* Relative to irq_base
*/
#define IRQ_TC6393_NAND 0
#define IRQ_TC6393_MMC 1
#define IRQ_TC6393_OHCI 2
+#define IRQ_TC6393_FB 4
#define TC6393XB_NR_IRQS 8