mirror of
https://github.com/genesi/linux-legacy.git
synced 2026-09-25 08:04:07 +00:00
display: go back to reserving a framebuffer so the base address doesn't move around on boot and make X go crazy.
8MB on Smartbook, 32MB on Smarttop. Dynamically allocating the framebuffer for 1920x1080-32 didn't work with the dynamic method anyway (sigh) due to memory fragmentation. Also, align framebuffer stride to 32 bytes to fix Z430 acceleration in X
This commit is contained in:
@@ -287,10 +287,48 @@ static struct sys_timer mx51_efikamx_timer = {
|
||||
static void __init mx51_efikamx_fixup(struct machine_desc *desc, struct tag *tags,
|
||||
char **cmdline, struct meminfo *mi)
|
||||
{
|
||||
struct tag *mem_tag = 0;
|
||||
int total_mem = SZ_512M;
|
||||
int sys_mem = 0;
|
||||
int fb_mem;
|
||||
|
||||
/*
|
||||
* a note on these sizes. we reserve enough memory to set up a framebuffer
|
||||
* of maximum size for the platform, with triple buffer, at maximum
|
||||
* reasonable bit depth. Since the Smartbook has a 16-bit LVDS interface
|
||||
* the most reasonable depth is 16-bit, hence 1280x720-16 * 3 is ~6MB
|
||||
* and we can get away with a minimal reservation of 8MB. For the Smarttop
|
||||
* the maximum resolution is 1920x1080-32 * 3 which is just over 24MB and
|
||||
* we reserve 32MB as it is a nice, round number
|
||||
*/
|
||||
|
||||
if (machine_is_mx51_efikasb()) {
|
||||
fb_mem = SZ_8M;
|
||||
} else if (machine_is_mx51_efikamx()) {
|
||||
fb_mem = SZ_32M;
|
||||
}
|
||||
|
||||
mxc_set_cpu_type(MXC_CPU_MX51);
|
||||
|
||||
get_cpu_wp = mx51_efikamx_get_cpu_wp;
|
||||
set_num_cpu_wp = mx51_efikamx_set_num_cpu_wp;
|
||||
|
||||
for_each_tag(mem_tag, tags) {
|
||||
if (mem_tag->hdr.tag == ATAG_MEM) {
|
||||
total_mem = mem_tag->u.mem.size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fb_mem) {
|
||||
sys_mem = total_mem - fb_mem;
|
||||
|
||||
if (mem_tag) {
|
||||
fb_mem = total_mem - fb_mem;
|
||||
mem_tag->u.mem.size = sys_mem;
|
||||
mx51_efikamx_display_adjust_mem(mem_tag->u.mem.start + sys_mem, fb_mem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
|
||||
extern int mx51_efikamx_revision(void);
|
||||
|
||||
/* move to mx51_efikamx.h */
|
||||
extern void __init mx51_efikamx_display_adjust_mem(unsigned int start, unsigned int size);
|
||||
|
||||
extern void __init mx51_efikamx_io_init(void);
|
||||
extern int __init mx51_efikamx_init_mc13892(void);
|
||||
extern void __init mx51_efikamx_timer_init(void);
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "../../../drivers/video/mxc/siihdmi.h"
|
||||
|
||||
|
||||
|
||||
extern void mx5_ipu_reset(void);
|
||||
static struct mxc_ipu_config mxc_ipu_data = {
|
||||
.rev = 2,
|
||||
@@ -188,7 +189,17 @@ static char *mxcfb_clocks[] = {
|
||||
};
|
||||
|
||||
|
||||
static struct resource mx51_efikamx_fb_resources[] = {
|
||||
[0] = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
void __init mx51_efikamx_display_adjust_mem(unsigned int start, unsigned int size)
|
||||
{
|
||||
mx51_efikamx_fb_resources[0].start = start;
|
||||
mx51_efikamx_fb_resources[0].end = start + size - 1;
|
||||
}
|
||||
|
||||
void __init mx51_efikamx_init_display(void)
|
||||
{
|
||||
@@ -252,14 +263,20 @@ void __init mx51_efikamx_init_display(void)
|
||||
* (DI0 on MX, DI1 on SB) first to make it the first framebuffer device.
|
||||
*/
|
||||
mxc_ipu_data.di_clk[display_id] = clk_get(NULL, mxcfb_clocks[display_id]);
|
||||
|
||||
mxc_fb_devices[display_id].num_resources = ARRAY_SIZE(mx51_efikamx_fb_resources);
|
||||
mxc_fb_devices[display_id].resource = mx51_efikamx_fb_resources;
|
||||
mxc_register_device(&mxc_fb_devices[display_id], &mx51_efikamx_display_data[display_id]);
|
||||
|
||||
#if defined(ANDROID_SUPPORT)
|
||||
/* register /dev/fb1 even though it's not used. We just register the other DI with the LVDS platform
|
||||
* data, since this is all it really needs to create the framebuffer, even though it just won't be
|
||||
* used for anything
|
||||
* used for anything. This actually won't work for now because there's some real weirdness about
|
||||
* the preallocated memory and a second framebuffer in the same resource area (it has no idea how
|
||||
* big the other framebuffer is..)
|
||||
*/
|
||||
mxc_register_device(&mxc_fb_devices[!display_id], &mx51_efikamx_display_data[EFIKASB_LVDS_DISPLAY_ID]);
|
||||
|
||||
#endif
|
||||
/* video overlay, absolutely must be /dev/fb2 and therefore registered after TWO framebuffers otherwise
|
||||
* the v4l2sink doesn't work right. This is probably actually a major bug in userspace somewhere..
|
||||
*/
|
||||
|
||||
@@ -75,6 +75,7 @@ struct mxcfb_info {
|
||||
void *alpha_virt_addr1;
|
||||
uint32_t alpha_mem_len;
|
||||
uint32_t ipu_ch_irq;
|
||||
uint32_t ipu_alp_ch_irq;
|
||||
uint32_t cur_ipu_buf;
|
||||
uint32_t cur_ipu_alpha_buf;
|
||||
|
||||
@@ -627,6 +628,13 @@ static int mxcfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
|
||||
if (var->xres_virtual < var->xres)
|
||||
var->xres_virtual = var->xres;
|
||||
|
||||
/*
|
||||
* pad xres_virtual to 32 pixels to make it more suitable for
|
||||
* gpu acceleration
|
||||
*/
|
||||
if (var->xres_virtual & 0x1f)
|
||||
var->xres_virtual = (var->xres_virtual + 31) & ~31;
|
||||
|
||||
/* Default Y virtual size is 3*yres */
|
||||
if (var->yres_virtual < (var->yres * 3))
|
||||
var->yres_virtual = (var->yres * 3);
|
||||
@@ -1475,10 +1483,12 @@ static int mxcfb_resume(struct platform_device *pdev)
|
||||
*/
|
||||
static int mxcfb_map_video_memory(struct fb_info *fbi)
|
||||
{
|
||||
if (fbi->fix.line_length == 0) fbi->fix.line_length = fbi->var.xres;
|
||||
if (fbi->fix.line_length == 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fbi->fix.smem_len = fbi->var.yres_virtual * fbi->fix.line_length;
|
||||
fbi->fix.smem_len = (fbi->fix.smem_len + SZ_1M - 1) & ~(SZ_1M - 1);
|
||||
if (fbi->fix.smem_len < fbi->var.yres_virtual * fbi->fix.line_length)
|
||||
fbi->fix.smem_len = fbi->var.yres_virtual * fbi->fix.line_length;
|
||||
|
||||
fbi->screen_base = dma_alloc_writecombine(fbi->device,
|
||||
fbi->fix.smem_len,
|
||||
@@ -1614,6 +1624,50 @@ static ssize_t swap_disp_chan(struct device *dev,
|
||||
}
|
||||
DEVICE_ATTR(fsl_disp_property, 644, show_disp_chan, swap_disp_chan);
|
||||
|
||||
static int mxcfb_setup(struct fb_info *fbi, struct platform_device *pdev)
|
||||
{
|
||||
struct mxcfb_info *mxcfbi = (struct mxcfb_info *) fbi->par;
|
||||
struct mxc_fb_platform_data *plat_data = pdev->dev.platform_data;
|
||||
int ret = 0;
|
||||
|
||||
/* default to 640x480@60 */
|
||||
fb_videomode_to_var(&fbi->var, &cea_modes[1]);
|
||||
|
||||
if (plat_data && !mxcfbi->ipu_di_pix_fmt) {
|
||||
mxcfbi->ipu_di_pix_fmt = plat_data->interface_pix_fmt;
|
||||
#if 0
|
||||
/* try and use a bit depth closest to the bit depth we use for the panel */
|
||||
if (!mxcfbi->default_bpp)
|
||||
mxcfbi->default_bpp = pixfmt_to_bpp(plat_data->interface_pix_fmt);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!mxcfbi->default_bpp)
|
||||
mxcfbi->default_bpp = 16;
|
||||
|
||||
if (plat_data && plat_data->mode && plat_data->num_modes)
|
||||
fb_videomode_to_modelist(plat_data->mode, plat_data->num_modes,
|
||||
&fbi->modelist);
|
||||
|
||||
if (!mxcfbi->fb_mode_str && plat_data && plat_data->mode_str)
|
||||
mxcfbi->fb_mode_str = plat_data->mode_str;
|
||||
|
||||
if (mxcfbi->fb_mode_str) {
|
||||
ret = fb_find_mode(&fbi->var, fbi, mxcfbi->fb_mode_str, NULL, 0, NULL,
|
||||
mxcfbi->default_bpp);
|
||||
if ((!ret || (ret > 2)) && plat_data && plat_data->mode && plat_data->num_modes)
|
||||
fb_find_mode(&fbi->var, fbi, mxcfbi->fb_mode_str, plat_data->mode,
|
||||
plat_data->num_modes, NULL, mxcfbi->default_bpp);
|
||||
}
|
||||
|
||||
|
||||
mxcfb_check_var(&fbi->var, fbi);
|
||||
mxcfb_set_fix(fbi);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* Probe routine for the framebuffer driver. It is called during the
|
||||
* driver binding process. The following functions are performed in
|
||||
@@ -1626,7 +1680,7 @@ static int mxcfb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct fb_info *fbi;
|
||||
struct mxcfb_info *mxcfbi;
|
||||
struct mxc_fb_platform_data *plat_data = pdev->dev.platform_data;
|
||||
struct resource *res;
|
||||
char *options;
|
||||
char name[] = "mxcdi0fb";
|
||||
int ret = 0;
|
||||
@@ -1659,6 +1713,7 @@ static int mxcfb_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
mxcfbi->ipu_di = pdev->id;
|
||||
mxcfbi->ipu_alp_ch_irq = -1;
|
||||
|
||||
if (pdev->id == 0) {
|
||||
ipu_disp_set_global_alpha(mxcfbi->ipu_ch, true, 0x80);
|
||||
@@ -1666,30 +1721,17 @@ static int mxcfb_probe(struct platform_device *pdev)
|
||||
strcpy(fbi->fix.id, "DISP3 BG");
|
||||
|
||||
if (!g_dp_in_use)
|
||||
if (ipu_request_irq(IPU_IRQ_BG_ALPHA_SYNC_EOF,
|
||||
mxcfb_alpha_irq_handler, 0,
|
||||
MXCFB_NAME, fbi) != 0) {
|
||||
dev_err(&pdev->dev, "Error registering BG "
|
||||
"alpha irq handler.\n");
|
||||
ret = -EBUSY;
|
||||
goto err1;
|
||||
}
|
||||
mxcfbi->ipu_alp_ch_irq = IPU_IRQ_BG_ALPHA_SYNC_EOF;
|
||||
g_dp_in_use = true;
|
||||
} else if (pdev->id == 1) {
|
||||
strcpy(fbi->fix.id, "DISP3 BG - DI1");
|
||||
|
||||
if (!g_dp_in_use)
|
||||
if (ipu_request_irq(IPU_IRQ_BG_ALPHA_SYNC_EOF,
|
||||
mxcfb_alpha_irq_handler, 0,
|
||||
MXCFB_NAME, fbi) != 0) {
|
||||
dev_err(&pdev->dev, "Error registering BG "
|
||||
"alpha irq handler.\n");
|
||||
ret = -EBUSY;
|
||||
goto err1;
|
||||
}
|
||||
mxcfbi->ipu_alp_ch_irq = IPU_IRQ_BG_ALPHA_SYNC_EOF;
|
||||
g_dp_in_use = true;
|
||||
} else if (pdev->id == 2) { /* Overlay */
|
||||
mxcfbi->ipu_ch_irq = IPU_IRQ_FG_SYNC_EOF;
|
||||
mxcfbi->ipu_alp_ch_irq = IPU_IRQ_FG_ALPHA_SYNC_EOF;
|
||||
mxcfbi->ipu_ch = MEM_FG_SYNC;
|
||||
mxcfbi->ipu_di = -1;
|
||||
mxcfbi->overlay = true;
|
||||
@@ -1697,14 +1739,6 @@ static int mxcfb_probe(struct platform_device *pdev)
|
||||
|
||||
strcpy(fbi->fix.id, "DISP3 FG");
|
||||
|
||||
if (ipu_request_irq(IPU_IRQ_FG_ALPHA_SYNC_EOF,
|
||||
mxcfb_alpha_irq_handler, 0,
|
||||
MXCFB_NAME, fbi) != 0) {
|
||||
dev_err(&pdev->dev, "Error registering FG alpha irq "
|
||||
"handler.\n");
|
||||
ret = -EBUSY;
|
||||
goto err1;
|
||||
}
|
||||
}
|
||||
|
||||
mxcfb_info[pdev->id] = fbi;
|
||||
@@ -1717,47 +1751,30 @@ static int mxcfb_probe(struct platform_device *pdev)
|
||||
}
|
||||
ipu_disable_irq(mxcfbi->ipu_ch_irq);
|
||||
|
||||
/* default to 640x480@60 */
|
||||
fb_videomode_to_var(&fbi->var, &cea_modes[1]);
|
||||
|
||||
if (plat_data && !mxcfbi->ipu_di_pix_fmt) {
|
||||
mxcfbi->ipu_di_pix_fmt = plat_data->interface_pix_fmt;
|
||||
#if 0
|
||||
/* try and use a bit depth closest to the bit depth we use for the panel */
|
||||
if (!mxcfbi->default_bpp)
|
||||
mxcfbi->default_bpp = pixfmt_to_bpp(plat_data->interface_pix_fmt);
|
||||
#endif
|
||||
if (mxcfbi->ipu_alp_ch_irq != -1) {
|
||||
if (ipu_request_irq(mxcfbi->ipu_alp_ch_irq,
|
||||
mxcfb_alpha_irq_handler, 0,
|
||||
MXCFB_NAME, fbi) != 0) {
|
||||
dev_err(&pdev->dev, "Error registering alpha irq handler.\n");
|
||||
ret = -EBUSY;
|
||||
goto err2;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mxcfbi->default_bpp)
|
||||
mxcfbi->default_bpp = 16;
|
||||
|
||||
if (plat_data && plat_data->mode && plat_data->num_modes)
|
||||
fb_videomode_to_modelist(plat_data->mode, plat_data->num_modes,
|
||||
&fbi->modelist);
|
||||
|
||||
if (!mxcfbi->fb_mode_str && plat_data && plat_data->mode_str)
|
||||
mxcfbi->fb_mode_str = plat_data->mode_str;
|
||||
|
||||
if (mxcfbi->fb_mode_str) {
|
||||
ret = fb_find_mode(&fbi->var, fbi, mxcfbi->fb_mode_str, NULL, 0, NULL,
|
||||
mxcfbi->default_bpp);
|
||||
if ((!ret || (ret > 2)) && plat_data && plat_data->mode && plat_data->num_modes)
|
||||
fb_find_mode(&fbi->var, fbi, mxcfbi->fb_mode_str, plat_data->mode,
|
||||
plat_data->num_modes, NULL, mxcfbi->default_bpp);
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (res && res->end) {
|
||||
fbi->fix.smem_len = res->end - res->start + 1;
|
||||
fbi->fix.smem_start = res->start;
|
||||
fbi->screen_base = ioremap(fbi->fix.smem_start, fbi->fix.smem_len);
|
||||
}
|
||||
|
||||
mxcfb_check_var(&fbi->var, fbi);
|
||||
|
||||
mxcfb_set_fix(fbi);
|
||||
|
||||
/* allocate fb first */
|
||||
if (mxcfb_map_video_memory(fbi) < 0)
|
||||
return -ENOMEM;
|
||||
ret = mxcfb_setup(fbi, pdev);
|
||||
if (ret < 0)
|
||||
goto err3;
|
||||
|
||||
ret = register_framebuffer(fbi);
|
||||
if (ret < 0)
|
||||
goto err2;
|
||||
goto err3;
|
||||
|
||||
platform_set_drvdata(pdev, fbi);
|
||||
|
||||
@@ -1767,6 +1784,9 @@ static int mxcfb_probe(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
|
||||
err3:
|
||||
if (mxcfbi->ipu_alp_ch_irq != -1)
|
||||
ipu_free_irq(mxcfbi->ipu_alp_ch_irq, fbi);
|
||||
err2:
|
||||
ipu_free_irq(mxcfbi->ipu_ch_irq, fbi);
|
||||
err1:
|
||||
|
||||
Reference in New Issue
Block a user