diff options
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/tc6393xb.c | 114 |
1 files changed, 114 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), |