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:
Matt Sealey
2011-07-28 17:59:54 -05:00
parent 46cf9c5817
commit 4ffd877f1b
4 changed files with 141 additions and 65 deletions

View File

@@ -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);
}
}
}

View File

@@ -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);

View File

@@ -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..
*/

View File

@@ -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: