mirror of
https://github.com/joel16/android_kernel_sony_msm8994.git
synced 2024-11-30 15:41:27 +00:00
ep93xx video driver platform support
Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> Acked-by: H Hartley Sweeten <hsweeten@visionengravers.com> Cc: Daniele Venzano <linux@brownhat.org> Cc: Russell King <rmk@arm.linux.org.uk> Cc: Krzysztof Helt <krzysztof.h1@poczta.fm> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
d63870db3c
commit
c6012189a4
@ -37,7 +37,7 @@ struct clk {
|
||||
static unsigned long get_uart_rate(struct clk *clk);
|
||||
|
||||
static int set_keytchclk_rate(struct clk *clk, unsigned long rate);
|
||||
|
||||
static int set_div_rate(struct clk *clk, unsigned long rate);
|
||||
|
||||
static struct clk clk_uart1 = {
|
||||
.sw_locked = 1,
|
||||
@ -76,6 +76,13 @@ static struct clk clk_pwm = {
|
||||
.rate = EP93XX_EXT_CLK_RATE,
|
||||
};
|
||||
|
||||
static struct clk clk_video = {
|
||||
.sw_locked = 1,
|
||||
.enable_reg = EP93XX_SYSCON_VIDCLKDIV,
|
||||
.enable_mask = EP93XX_SYSCON_CLKDIV_ENABLE,
|
||||
.set_rate = set_div_rate,
|
||||
};
|
||||
|
||||
/* DMA Clocks */
|
||||
static struct clk clk_m2p0 = {
|
||||
.enable_reg = EP93XX_SYSCON_PWRCNT,
|
||||
@ -140,6 +147,7 @@ static struct clk_lookup clocks[] = {
|
||||
INIT_CK(NULL, "pll2", &clk_pll2),
|
||||
INIT_CK("ep93xx-ohci", NULL, &clk_usb_host),
|
||||
INIT_CK("ep93xx-keypad", NULL, &clk_keypad),
|
||||
INIT_CK("ep93xx-fb", NULL, &clk_video),
|
||||
INIT_CK(NULL, "pwm_clk", &clk_pwm),
|
||||
INIT_CK(NULL, "m2p0", &clk_m2p0),
|
||||
INIT_CK(NULL, "m2p1", &clk_m2p1),
|
||||
@ -236,6 +244,84 @@ static int set_keytchclk_rate(struct clk *clk, unsigned long rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long calc_clk_div(unsigned long rate, int *psel, int *esel,
|
||||
int *pdiv, int *div)
|
||||
{
|
||||
unsigned long max_rate, best_rate = 0,
|
||||
actual_rate = 0, mclk_rate = 0, rate_err = -1;
|
||||
int i, found = 0, __div = 0, __pdiv = 0;
|
||||
|
||||
/* Don't exceed the maximum rate */
|
||||
max_rate = max(max(clk_pll1.rate / 4, clk_pll2.rate / 4),
|
||||
(unsigned long)EP93XX_EXT_CLK_RATE / 4);
|
||||
rate = min(rate, max_rate);
|
||||
|
||||
/*
|
||||
* Try the two pll's and the external clock
|
||||
* Because the valid predividers are 2, 2.5 and 3, we multiply
|
||||
* all the clocks by 2 to avoid floating point math.
|
||||
*
|
||||
* This is based on the algorithm in the ep93xx raster guide:
|
||||
* http://be-a-maverick.com/en/pubs/appNote/AN269REV1.pdf
|
||||
*
|
||||
*/
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (i == 0)
|
||||
mclk_rate = EP93XX_EXT_CLK_RATE * 2;
|
||||
else if (i == 1)
|
||||
mclk_rate = clk_pll1.rate * 2;
|
||||
else if (i == 2)
|
||||
mclk_rate = clk_pll2.rate * 2;
|
||||
|
||||
/* Try each predivider value */
|
||||
for (__pdiv = 4; __pdiv <= 6; __pdiv++) {
|
||||
__div = mclk_rate / (rate * __pdiv);
|
||||
if (__div < 2 || __div > 127)
|
||||
continue;
|
||||
|
||||
actual_rate = mclk_rate / (__pdiv * __div);
|
||||
|
||||
if (!found || abs(actual_rate - rate) < rate_err) {
|
||||
*pdiv = __pdiv - 3;
|
||||
*div = __div;
|
||||
*psel = (i == 2);
|
||||
*esel = (i != 0);
|
||||
best_rate = actual_rate;
|
||||
rate_err = abs(actual_rate - rate);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return 0;
|
||||
|
||||
return best_rate;
|
||||
}
|
||||
|
||||
static int set_div_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long actual_rate;
|
||||
int psel = 0, esel = 0, pdiv = 0, div = 0;
|
||||
u32 val;
|
||||
|
||||
actual_rate = calc_clk_div(rate, &psel, &esel, &pdiv, &div);
|
||||
if (actual_rate == 0)
|
||||
return -EINVAL;
|
||||
clk->rate = actual_rate;
|
||||
|
||||
/* Clear the esel, psel, pdiv and div bits */
|
||||
val = __raw_readl(clk->enable_reg);
|
||||
val &= ~0x7fff;
|
||||
|
||||
/* Set the new esel, psel, pdiv and div bits for the new clock rate */
|
||||
val |= (esel ? EP93XX_SYSCON_CLKDIV_ESEL : 0) |
|
||||
(psel ? EP93XX_SYSCON_CLKDIV_PSEL : 0) |
|
||||
(pdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | div;
|
||||
ep93xx_syscon_swlocked_write(val, clk->enable_reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
if (clk->set_rate)
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <linux/i2c-gpio.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/fb.h>
|
||||
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/time.h>
|
||||
@ -682,6 +683,37 @@ void ep93xx_pwm_release_gpio(struct platform_device *pdev)
|
||||
EXPORT_SYMBOL(ep93xx_pwm_release_gpio);
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* EP93xx video peripheral handling
|
||||
*************************************************************************/
|
||||
static struct ep93xxfb_mach_info ep93xxfb_data;
|
||||
|
||||
static struct resource ep93xx_fb_resource[] = {
|
||||
{
|
||||
.start = EP93XX_RASTER_PHYS_BASE,
|
||||
.end = EP93XX_RASTER_PHYS_BASE + 0x800 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device ep93xx_fb_device = {
|
||||
.name = "ep93xx-fb",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &ep93xxfb_data,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.dma_mask = &ep93xx_fb_device.dev.coherent_dma_mask,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(ep93xx_fb_resource),
|
||||
.resource = ep93xx_fb_resource,
|
||||
};
|
||||
|
||||
void __init ep93xx_register_fb(struct ep93xxfb_mach_info *data)
|
||||
{
|
||||
ep93xxfb_data = *data;
|
||||
platform_device_register(&ep93xx_fb_device);
|
||||
}
|
||||
|
||||
extern void ep93xx_gpio_init(void);
|
||||
|
||||
void __init ep93xx_init_devices(void)
|
||||
|
@ -70,6 +70,7 @@
|
||||
#define EP93XX_USB_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00020000)
|
||||
#define EP93XX_USB_BASE EP93XX_AHB_IOMEM(0x00020000)
|
||||
|
||||
#define EP93XX_RASTER_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00030000)
|
||||
#define EP93XX_RASTER_BASE EP93XX_AHB_IOMEM(0x00030000)
|
||||
|
||||
#define EP93XX_GRAPHICS_ACCEL_BASE EP93XX_AHB_IOMEM(0x00040000)
|
||||
@ -207,6 +208,11 @@
|
||||
#define EP93XX_SYSCON_DEVCFG_ADCPD (1<<2)
|
||||
#define EP93XX_SYSCON_DEVCFG_KEYS (1<<1)
|
||||
#define EP93XX_SYSCON_DEVCFG_SHENA (1<<0)
|
||||
#define EP93XX_SYSCON_VIDCLKDIV EP93XX_SYSCON_REG(0x84)
|
||||
#define EP93XX_SYSCON_CLKDIV_ENABLE (1<<15)
|
||||
#define EP93XX_SYSCON_CLKDIV_ESEL (1<<14)
|
||||
#define EP93XX_SYSCON_CLKDIV_PSEL (1<<13)
|
||||
#define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV EP93XX_SYSCON_REG(0x90)
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN (1<<31)
|
||||
#define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV (1<<16)
|
||||
|
56
arch/arm/mach-ep93xx/include/mach/fb.h
Normal file
56
arch/arm/mach-ep93xx/include/mach/fb.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* arch/arm/mach-ep93xx/include/mach/fb.h
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_EP93XXFB_H
|
||||
#define __ASM_ARCH_EP93XXFB_H
|
||||
|
||||
struct platform_device;
|
||||
struct fb_videomode;
|
||||
struct fb_info;
|
||||
|
||||
#define EP93XXFB_USE_MODEDB 0
|
||||
|
||||
/* VideoAttributes flags */
|
||||
#define EP93XXFB_STATE_MACHINE_ENABLE (1 << 0)
|
||||
#define EP93XXFB_PIXEL_CLOCK_ENABLE (1 << 1)
|
||||
#define EP93XXFB_VSYNC_ENABLE (1 << 2)
|
||||
#define EP93XXFB_PIXEL_DATA_ENABLE (1 << 3)
|
||||
#define EP93XXFB_COMPOSITE_SYNC (1 << 4)
|
||||
#define EP93XXFB_SYNC_VERT_HIGH (1 << 5)
|
||||
#define EP93XXFB_SYNC_HORIZ_HIGH (1 << 6)
|
||||
#define EP93XXFB_SYNC_BLANK_HIGH (1 << 7)
|
||||
#define EP93XXFB_PCLK_FALLING (1 << 8)
|
||||
#define EP93XXFB_ENABLE_AC (1 << 9)
|
||||
#define EP93XXFB_ENABLE_LCD (1 << 10)
|
||||
#define EP93XXFB_ENABLE_CCIR (1 << 12)
|
||||
#define EP93XXFB_USE_PARALLEL_INTERFACE (1 << 13)
|
||||
#define EP93XXFB_ENABLE_INTERRUPT (1 << 14)
|
||||
#define EP93XXFB_USB_INTERLACE (1 << 16)
|
||||
#define EP93XXFB_USE_EQUALIZATION (1 << 17)
|
||||
#define EP93XXFB_USE_DOUBLE_HORZ (1 << 18)
|
||||
#define EP93XXFB_USE_DOUBLE_VERT (1 << 19)
|
||||
#define EP93XXFB_USE_BLANK_PIXEL (1 << 20)
|
||||
#define EP93XXFB_USE_SDCSN0 (0 << 21)
|
||||
#define EP93XXFB_USE_SDCSN1 (1 << 21)
|
||||
#define EP93XXFB_USE_SDCSN2 (2 << 21)
|
||||
#define EP93XXFB_USE_SDCSN3 (3 << 21)
|
||||
|
||||
#define EP93XXFB_ENABLE (EP93XXFB_STATE_MACHINE_ENABLE | \
|
||||
EP93XXFB_PIXEL_CLOCK_ENABLE | \
|
||||
EP93XXFB_VSYNC_ENABLE | \
|
||||
EP93XXFB_PIXEL_DATA_ENABLE)
|
||||
|
||||
struct ep93xxfb_mach_info {
|
||||
unsigned int num_modes;
|
||||
const struct fb_videomode *modes;
|
||||
const struct fb_videomode *default_mode;
|
||||
int bpp;
|
||||
unsigned int flags;
|
||||
|
||||
int (*setup)(struct platform_device *pdev);
|
||||
void (*teardown)(struct platform_device *pdev);
|
||||
void (*blank)(int blank_mode, struct fb_info *info);
|
||||
};
|
||||
|
||||
#endif /* __ASM_ARCH_EP93XXFB_H */
|
@ -6,6 +6,7 @@
|
||||
|
||||
struct i2c_board_info;
|
||||
struct platform_device;
|
||||
struct ep93xxfb_mach_info;
|
||||
|
||||
struct ep93xx_eth_data
|
||||
{
|
||||
@ -33,6 +34,7 @@ static inline void ep93xx_devcfg_clear_bits(unsigned int bits)
|
||||
|
||||
void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
|
||||
void ep93xx_register_i2c(struct i2c_board_info *devices, int num);
|
||||
void ep93xx_register_fb(struct ep93xxfb_mach_info *data);
|
||||
void ep93xx_register_pwm(int pwm0, int pwm1);
|
||||
int ep93xx_pwm_acquire_gpio(struct platform_device *pdev);
|
||||
void ep93xx_pwm_release_gpio(struct platform_device *pdev);
|
||||
|
Loading…
Reference in New Issue
Block a user