* RE: [PATCH] unicore32 framebuffer driver fix: make videomemory kmalloc-ed and floatable
From: Guan Xuetao @ 2011-03-30 1:39 UTC (permalink / raw)
To: 'Arnd Bergmann'; +Cc: 'Paul Mundt', linux-kernel, linux-fbdev
In-Reply-To: <201103291642.49555.arnd@arndb.de>
> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: Tuesday, March 29, 2011 10:43 PM
> To: Guan Xuetao
> Cc: Paul Mundt; linux-kernel@vger.kernel.org; linux-fbdev@vger.kernel.org
> Subject: Re: [PATCH] unicore32 framebuffer driver fix: make videomemory kmalloc-ed and floatable
>
> On Tuesday 29 March 2011, Guan Xuetao wrote:
> >
> > 1. make videomemory kmalloc-ed in fb-puv3.c
> > 2. remove resource reservation for old fixed UNIGFX_MMAP & UVC_MMAP space
> > 3. remove unused PKUNTIY_UNIGFX_MMAP_BASE, PKUNITY_UNIGFX_MMAP_SIZE,
> > PKUNITY_UVC_MMAP_BASE, PKUNITY_UVC_MMAP_SIZE and KUSER_UNIGFX_BASE
> > 4. remove unused header linux/vmalloc.h in fb-puv3.c
> >
> > Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
>
> How does this work? UNIFB_MEMSIZE seems to be 4 MB, much more than the
> maximum of 128 KB that kmalloc can allocate.
>
> Shouldn't this use get_free_pages() instead of kmalloc?
>
> Arnd
When using SLUB allocator, if required memory size is larger than 2*PAGE_SIZE, kmalloc_large is called,
and eventually __get_free_pages will be called.
So, it would be the same as __get_free_pages.
^ permalink raw reply
* [PATCH] s3fb: fix Virge/GX2
From: Ondrej Zary @ 2011-03-29 19:07 UTC (permalink / raw)
To: Ondrej Zajicek; +Cc: linux-fbdev, Kernel development list, Paul Mundt
Fix Virge/GX2 support in s3fb:
- fix IDs: 86C357 is GX2, 86C359 is GX2+, 86C356 probably does not exist
- add memory size detection
- drive it the same way as Trio3D/2X
The original IDs most likely came from S3 website which claims that:
- 356 is Virge/GX2 with IDŠ10, driver included in Windows 2K, XP
- 357 is Virge/GX2+ with IDŠ11, driver included in Windows ME
- 359 is Virge/GX2+ with IDŠ12, driver included in Windows ME
but:
- google search for 86C356 only reveals references to Trio3D (probably
because of a typo - Trio3D is 86C365)
- my card is clearly marked as 86C357, Virge/GX2 and has IDŠ10
- there is no driver for IDs 8A11 and 8A12 in Windows ME
- there is a driver for ID 8A10 in Windows ME that says it's GX2 (357)
Tested with #9 Reality 334 (86C357 Virge/GX2, ID=0x8A10).
Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
--- linux-2.6.38-rc4-/drivers/video/s3fb.c 2011-03-29 17:17:48.000000000 +0200
+++ linux-2.6.38-rc4/drivers/video/s3fb.c 2011-03-29 20:25:12.000000000 +0200
@@ -71,9 +71,9 @@ static const int s3_memsizes[] = {4096,
static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", "S3 Trio64V+",
"S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX",
- "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge",
+ "S3 Plato/PX", "S3 Aurora64V+", "S3 Virge",
"S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX",
- "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P",
+ "S3 Virge/GX2", "S3 Virge/GX2+", "",
"S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X",
"S3 Trio3D"};
@@ -90,9 +90,8 @@ static const char * const s3_names[] = {
#define CHIP_988_VIRGE_VX 0x0A
#define CHIP_375_VIRGE_DX 0x0B
#define CHIP_385_VIRGE_GX 0x0C
-#define CHIP_356_VIRGE_GX2 0x0D
-#define CHIP_357_VIRGE_GX2P 0x0E
-#define CHIP_359_VIRGE_GX2P 0x0F
+#define CHIP_357_VIRGE_GX2 0x0D
+#define CHIP_359_VIRGE_GX2P 0x0E
#define CHIP_360_TRIO3D_1X 0x10
#define CHIP_362_TRIO3D_2X 0x11
#define CHIP_368_TRIO3D_2X 0x12
@@ -359,7 +358,9 @@ static void s3_set_pixclock(struct fb_in
vga_w(par->state.vgabase, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
/* Set S3 clock registers */
- if (par->chip = CHIP_360_TRIO3D_1X ||
+ if (par->chip = CHIP_357_VIRGE_GX2 ||
+ par->chip = CHIP_359_VIRGE_GX2P ||
+ par->chip = CHIP_360_TRIO3D_1X ||
par->chip = CHIP_362_TRIO3D_2X ||
par->chip = CHIP_368_TRIO3D_2X) {
vga_wseq(par->state.vgabase, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */
@@ -560,7 +561,9 @@ static int s3fb_set_par(struct fb_info *
pr_debug("fb%d: offset register : %d\n", info->node, offset_value);
svga_wcrt_multi(par->state.vgabase, s3_offset_regs, offset_value);
- if (par->chip != CHIP_360_TRIO3D_1X &&
+ if (par->chip != CHIP_357_VIRGE_GX2 &&
+ par->chip != CHIP_359_VIRGE_GX2P &&
+ par->chip != CHIP_360_TRIO3D_1X &&
par->chip != CHIP_362_TRIO3D_2X &&
par->chip != CHIP_368_TRIO3D_2X) {
vga_wcrt(par->state.vgabase, 0x54, 0x18); /* M parameter */
@@ -604,7 +607,9 @@ static int s3fb_set_par(struct fb_info *
vga_wcrt(par->state.vgabase, 0x66, 0x90);
}
- if (par->chip = CHIP_360_TRIO3D_1X ||
+ if (par->chip = CHIP_357_VIRGE_GX2 ||
+ par->chip = CHIP_359_VIRGE_GX2P ||
+ par->chip = CHIP_360_TRIO3D_1X ||
par->chip = CHIP_362_TRIO3D_2X ||
par->chip = CHIP_368_TRIO3D_2X ||
par->chip = CHIP_365_TRIO3D ||
@@ -617,8 +622,7 @@ static int s3fb_set_par(struct fb_info *
vga_wcrt(par->state.vgabase, 0x66, 0x81);
}
- if (par->chip = CHIP_356_VIRGE_GX2 ||
- par->chip = CHIP_357_VIRGE_GX2P ||
+ if (par->chip = CHIP_357_VIRGE_GX2 ||
par->chip = CHIP_359_VIRGE_GX2P ||
par->chip = CHIP_360_TRIO3D_1X ||
par->chip = CHIP_362_TRIO3D_2X ||
@@ -674,6 +678,8 @@ static int s3fb_set_par(struct fb_info *
pr_debug("fb%d: 8 bit pseudocolor\n", info->node);
svga_wcrt_mask(par->state.vgabase, 0x50, 0x00, 0x30);
if (info->var.pixclock > 20000 ||
+ par->chip = CHIP_357_VIRGE_GX2 ||
+ par->chip = CHIP_359_VIRGE_GX2P ||
par->chip = CHIP_360_TRIO3D_1X ||
par->chip = CHIP_362_TRIO3D_2X ||
par->chip = CHIP_368_TRIO3D_2X)
@@ -702,7 +708,9 @@ static int s3fb_set_par(struct fb_info *
} else {
svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
svga_wcrt_mask(par->state.vgabase, 0x67, 0x30, 0xF0);
- if (par->chip != CHIP_360_TRIO3D_1X &&
+ if (par->chip != CHIP_357_VIRGE_GX2 &&
+ par->chip != CHIP_359_VIRGE_GX2P &&
+ par->chip != CHIP_360_TRIO3D_1X &&
par->chip != CHIP_362_TRIO3D_2X &&
par->chip != CHIP_368_TRIO3D_2X)
hmul = 2;
@@ -727,7 +735,9 @@ static int s3fb_set_par(struct fb_info *
} else {
svga_wcrt_mask(par->state.vgabase, 0x50, 0x10, 0x30);
svga_wcrt_mask(par->state.vgabase, 0x67, 0x50, 0xF0);
- if (par->chip != CHIP_360_TRIO3D_1X &&
+ if (par->chip != CHIP_357_VIRGE_GX2 &&
+ par->chip != CHIP_359_VIRGE_GX2P &&
+ par->chip != CHIP_360_TRIO3D_1X &&
par->chip != CHIP_362_TRIO3D_2X &&
par->chip != CHIP_368_TRIO3D_2X)
hmul = 2;
@@ -1069,6 +1079,16 @@ static int __devinit s3_pci_probe(struct
info->screen_size = 2 << 20;
break;
}
+ } else if (par->chip = CHIP_357_VIRGE_GX2 ||
+ par->chip = CHIP_359_VIRGE_GX2P) {
+ switch ((regval & 0xC0) >> 6) {
+ case 1: /* 4MB */
+ info->screen_size = 4 << 20;
+ break;
+ case 3: /* 2MB */
+ info->screen_size = 2 << 20;
+ break;
+ }
} else
info->screen_size = s3_memsizes[regval >> 5] << 10;
info->fix.smem_len = info->screen_size;
@@ -1275,8 +1295,8 @@ static struct pci_device_id s3_devices[]
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x5631), .driver_data = CHIP_325_VIRGE},
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x883D), .driver_data = CHIP_988_VIRGE_VX},
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A01), .driver_data = CHIP_XXX_VIRGE_DXGX},
- {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2},
- {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P},
+ {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_357_VIRGE_GX2},
+ {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_359_VIRGE_GX2P},
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P},
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X},
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8904), .driver_data = CHIP_365_TRIO3D},
--
Ondrej Zary
^ permalink raw reply
* RE: [PATCH] unicore32 framebuffer driver fix: make videomemory kmalloc-ed and floatable
From: Guan Xuetao @ 2011-03-29 14:54 UTC (permalink / raw)
To: 'Arnd Bergmann'; +Cc: 'Paul Mundt', linux-kernel, linux-fbdev
In-Reply-To: <201103291642.49555.arnd@arndb.de>
> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: Tuesday, March 29, 2011 10:43 PM
> To: Guan Xuetao
> Cc: Paul Mundt; linux-kernel@vger.kernel.org; linux-fbdev@vger.kernel.org
> Subject: Re: [PATCH] unicore32 framebuffer driver fix: make videomemory kmalloc-ed and floatable
>
> On Tuesday 29 March 2011, Guan Xuetao wrote:
> >
> > 1. make videomemory kmalloc-ed in fb-puv3.c
> > 2. remove resource reservation for old fixed UNIGFX_MMAP & UVC_MMAP space
> > 3. remove unused PKUNTIY_UNIGFX_MMAP_BASE, PKUNITY_UNIGFX_MMAP_SIZE,
> > PKUNITY_UVC_MMAP_BASE, PKUNITY_UVC_MMAP_SIZE and KUSER_UNIGFX_BASE
> > 4. remove unused header linux/vmalloc.h in fb-puv3.c
> >
> > Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
>
> How does this work? UNIFB_MEMSIZE seems to be 4 MB, much more than the
> maximum of 128 KB that kmalloc can allocate.
I'm surprised. But kmalloc() returns success with 0xc7000000.
>
> Shouldn't this use get_free_pages() instead of kmalloc?
I will check and correct it.
>
> Arnd
Thanks.
Guan Xuetao
^ permalink raw reply
* Re: [PATCH] unicore32 framebuffer driver fix: make videomemory kmalloc-ed and floatable
From: Arnd Bergmann @ 2011-03-29 14:42 UTC (permalink / raw)
To: Guan Xuetao; +Cc: Paul Mundt, linux-kernel, linux-fbdev
In-Reply-To: <019701cbee1e$c4e2d260$4ea87720$@mprc.pku.edu.cn>
On Tuesday 29 March 2011, Guan Xuetao wrote:
>
> 1. make videomemory kmalloc-ed in fb-puv3.c
> 2. remove resource reservation for old fixed UNIGFX_MMAP & UVC_MMAP space
> 3. remove unused PKUNTIY_UNIGFX_MMAP_BASE, PKUNITY_UNIGFX_MMAP_SIZE,
> PKUNITY_UVC_MMAP_BASE, PKUNITY_UVC_MMAP_SIZE and KUSER_UNIGFX_BASE
> 4. remove unused header linux/vmalloc.h in fb-puv3.c
>
> Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
How does this work? UNIFB_MEMSIZE seems to be 4 MB, much more than the
maximum of 128 KB that kmalloc can allocate.
Shouldn't this use get_free_pages() instead of kmalloc?
Arnd
^ permalink raw reply
* [PATCH] unicore32 framebuffer driver fix: make videomemory kmalloc-ed and floatable
From: Guan Xuetao @ 2011-03-29 14:37 UTC (permalink / raw)
To: Paul Mundt
Cc: Arnd Bergmann, 'Guan Xuetao', linux-kernel, linux-fbdev
1. make videomemory kmalloc-ed in fb-puv3.c
2. remove resource reservation for old fixed UNIGFX_MMAP & UVC_MMAP space
3. remove unused PKUNTIY_UNIGFX_MMAP_BASE, PKUNITY_UNIGFX_MMAP_SIZE,
PKUNITY_UVC_MMAP_BASE, PKUNITY_UVC_MMAP_SIZE and KUSER_UNIGFX_BASE
4. remove unused header linux/vmalloc.h in fb-puv3.c
Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
---
arch/unicore32/include/mach/PKUnity.h | 10 ----------
arch/unicore32/include/mach/memory.h | 1 -
arch/unicore32/kernel/puv3-core.c | 5 -----
arch/unicore32/kernel/setup.c | 15 ++-------------
arch/unicore32/mm/mmu.c | 20 --------------------
drivers/video/fb-puv3.c | 27 ++++++++++++++++-----------
6 files changed, 18 insertions(+), 60 deletions(-)
diff --git a/arch/unicore32/include/mach/PKUnity.h b/arch/unicore32/include/mach/PKUnity.h
index a18bdc3..8040d57 100644
--- a/arch/unicore32/include/mach/PKUnity.h
+++ b/arch/unicore32/include/mach/PKUnity.h
@@ -24,16 +24,6 @@
#define PKUNITY_MMIO_BASE 0x80000000 /* 0x80000000 - 0xFFFFFFFF 2GB */
/*
- * PKUNITY Memory Map Addresses: 0x0D000000 - 0x0EFFFFFF (32MB)
- * 0x0D000000 - 0x0DFFFFFF 16MB: for UVC
- * 0x0E000000 - 0x0EFFFFFF 16MB: for UNIGFX
- */
-#define PKUNITY_UVC_MMAP_BASE 0x0D000000
-#define PKUNITY_UVC_MMAP_SIZE 0x01000000 /* 16MB */
-#define PKUNITY_UNIGFX_MMAP_BASE 0x0E000000
-#define PKUNITY_UNIGFX_MMAP_SIZE 0x01000000 /* 16MB */
-
-/*
* PKUNITY System Bus Addresses (PCI): 0x80000000 - 0xBFFFFFFF (1GB)
* 0x80000000 - 0x8000000B 12B PCI Configuration regs
* 0x80010000 - 0x80010250 592B PCI Bridge Base
diff --git a/arch/unicore32/include/mach/memory.h b/arch/unicore32/include/mach/memory.h
index 0bf21c9..4be72c2 100644
--- a/arch/unicore32/include/mach/memory.h
+++ b/arch/unicore32/include/mach/memory.h
@@ -50,7 +50,6 @@ void puv3_pci_adjust_zones(unsigned long *size, unsigned long *holes);
/* kuser area */
#define KUSER_VECPAGE_BASE (KUSER_BASE + UL(0x3fff0000))
-#define KUSER_UNIGFX_BASE (PAGE_OFFSET + PKUNITY_UNIGFX_MMAP_BASE)
/* kuser_vecpage (0xbfff0000) is ro, and vectors page (0xffff0000) is rw */
#define kuser_vecpage_to_vectors(x) ((x) - (KUSER_VECPAGE_BASE) \
+ (VECTORS_BASE))
diff --git a/arch/unicore32/kernel/puv3-core.c b/arch/unicore32/kernel/puv3-core.c
index 8b1b6be..1a505a7 100644
--- a/arch/unicore32/kernel/puv3-core.c
+++ b/arch/unicore32/kernel/puv3-core.c
@@ -99,11 +99,6 @@ static struct resource puv3_unigfx_resources[] = {
.end = io_v2p(PKUNITY_UNIGFX_BASE) + 0xfff,
.flags = IORESOURCE_MEM,
},
- [1] = {
- .start = PKUNITY_UNIGFX_MMAP_BASE,
- .end = PKUNITY_UNIGFX_MMAP_BASE + PKUNITY_UNIGFX_MMAP_SIZE,
- .flags = IORESOURCE_MEM,
- },
};
static struct resource puv3_rtc_resources[] = {
diff --git a/arch/unicore32/kernel/setup.c b/arch/unicore32/kernel/setup.c
index 1e175a8..471b6bc 100644
--- a/arch/unicore32/kernel/setup.c
+++ b/arch/unicore32/kernel/setup.c
@@ -64,12 +64,6 @@ static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
*/
static struct resource mem_res[] = {
{
- .name = "Video RAM",
- .start = 0,
- .end = 0,
- .flags = IORESOURCE_MEM
- },
- {
.name = "Kernel text",
.start = 0,
.end = 0,
@@ -83,9 +77,8 @@ static struct resource mem_res[] = {
}
};
-#define video_ram mem_res[0]
-#define kernel_code mem_res[1]
-#define kernel_data mem_res[2]
+#define kernel_code mem_res[0]
+#define kernel_data mem_res[1]
/*
* These functions re-use the assembly code in head.S, which
@@ -224,10 +217,6 @@ request_standard_resources(struct meminfo *mi)
kernel_data.end <= res->end)
request_resource(res, &kernel_data);
}
-
- video_ram.start = PKUNITY_UNIGFX_MMAP_BASE;
- video_ram.end = PKUNITY_UNIGFX_MMAP_BASE + PKUNITY_UNIGFX_MMAP_SIZE;
- request_resource(&iomem_resource, &video_ram);
}
static void (*init_machine)(void) __initdata;
diff --git a/arch/unicore32/mm/mmu.c b/arch/unicore32/mm/mmu.c
index 7bf3d58..db2d334 100644
--- a/arch/unicore32/mm/mmu.c
+++ b/arch/unicore32/mm/mmu.c
@@ -338,15 +338,6 @@ void __init uc32_mm_memblock_reserve(void)
* and can only be in node 0.
*/
memblock_reserve(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t));
-
-#ifdef CONFIG_PUV3_UNIGFX
- /*
- * These should likewise go elsewhere. They pre-reserve the
- * screen/video memory region at the 48M~64M of main system memory.
- */
- memblock_reserve(PKUNITY_UNIGFX_MMAP_BASE, PKUNITY_UNIGFX_MMAP_SIZE);
- memblock_reserve(PKUNITY_UVC_MMAP_BASE, PKUNITY_UVC_MMAP_SIZE);
-#endif
}
/*
@@ -371,17 +362,6 @@ static void __init devicemaps_init(void)
pmd_clear(pmd_off_k(addr));
/*
- * Create a mapping for UniGFX VRAM
- */
-#ifdef CONFIG_PUV3_UNIGFX
- map.pfn = __phys_to_pfn(PKUNITY_UNIGFX_MMAP_BASE);
- map.virtual = KUSER_UNIGFX_BASE;
- map.length = PKUNITY_UNIGFX_MMAP_SIZE;
- map.type = MT_KUSER;
- create_mapping(&map);
-#endif
-
- /*
* Create a mapping for the machine vectors at the high-vectors
* location (0xffff0000). If we aren't using high-vectors, also
* create a mapping at the low-vectors virtual address.
diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c
index dbd2dc4..286e295 100644
--- a/drivers/video/fb-puv3.c
+++ b/drivers/video/fb-puv3.c
@@ -13,7 +13,6 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/vmalloc.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/fb.h>
@@ -531,7 +530,7 @@ static int unifb_set_par(struct fb_info *info)
return -EINVAL;
}
- writel(PKUNITY_UNIGFX_MMAP_BASE, UDE_FSA);
+ writel(info->fix.smem_start, UDE_FSA);
writel(info->var.yres, UDE_LS);
writel(get_line_length(info->var.xres,
info->var.bits_per_pixel) >> 3, UDE_PS);
@@ -680,13 +679,26 @@ static int unifb_probe(struct platform_device *dev)
struct fb_info *info;
u32 unifb_regs[UNIFB_REGS_NUM];
int retval = -ENOMEM;
- struct resource *iomem, *mapmem;
+ struct resource *iomem;
+ void *videomemory;
+
+ videomemory = kmalloc(UNIFB_MEMSIZE, GFP_KERNEL);
+ if (!videomemory)
+ goto err;
+
+ memset(videomemory, 0, UNIFB_MEMSIZE);
+
+ unifb_fix.smem_start = virt_to_phys(videomemory);
+ unifb_fix.smem_len = UNIFB_MEMSIZE;
+
+ iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ unifb_fix.mmio_start = iomem->start;
info = framebuffer_alloc(sizeof(u32)*256, &dev->dev);
if (!info)
goto err;
- info->screen_base = (char __iomem *)KUSER_UNIGFX_BASE;
+ info->screen_base = (char __iomem *)videomemory;
info->fbops = &unifb_ops;
retval = fb_find_mode(&info->var, info, NULL,
@@ -695,13 +707,6 @@ static int unifb_probe(struct platform_device *dev)
if (!retval || (retval = 4))
info->var = unifb_default;
- iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
- unifb_fix.mmio_start = iomem->start;
-
- mapmem = platform_get_resource(dev, IORESOURCE_MEM, 1);
- unifb_fix.smem_start = mapmem->start;
- unifb_fix.smem_len = UNIFB_MEMSIZE;
-
info->fix = unifb_fix;
info->pseudo_palette = info->par;
info->par = NULL;
--
1.6.2.2
^ permalink raw reply related
* Re: [patch] backlight/pcf50633: check for NULL consistently in pcf50633_bl_probe()
From: Lars-Peter Clausen @ 2011-03-29 11:19 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <20110329032020.GD9856@bicker>
On 03/29/2011 05:20 AM, Dan Carpenter wrote:
> We checked "pdata" for NULL at the start of the function so we should
> check it here as well.
>
> Signed-off-by: Dan Carpenter <error27@gmail.com>
Acked-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> Compile tested only. Please review.
>
> diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c
> index ef5628d..0fe934f 100644
> --- a/drivers/video/backlight/pcf50633-backlight.c
> +++ b/drivers/video/backlight/pcf50633-backlight.c
> @@ -136,7 +136,9 @@ static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
>
> platform_set_drvdata(pdev, pcf_bl);
>
> - pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM, pdata->ramp_time);
> + if (pdata)
> + pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM,
> + pdata->ramp_time);
>
> /* Should be different from bl_props.brightness, so we do not exit
> * update_status early the first time it's called */
^ permalink raw reply
* Re: [patch] backlight/ld9040.c: testing the wrong variable in
From: Donghwa Lee @ 2011-03-29 4:37 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <20110329031909.GC9856@bicker>
On 2011-03-29, Dan Carpenter wrote:
> We should be testing "bd" here instead of "ld". It's a copy and
> paste bug.
>
> Signed-off-by: Dan Carpenter <error27@gmail.com>
>
> diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c
> index 7281b25..9e81d69 100644
> --- a/drivers/video/backlight/ld9040.c
> +++ b/drivers/video/backlight/ld9040.c
> @@ -701,8 +701,8 @@ static int ld9040_probe(struct spi_device *spi)
>
> bd = backlight_device_register("ld9040-bl", &spi->dev,
> lcd, &ld9040_backlight_ops, NULL);
> - if (IS_ERR(ld)) {
> - ret = PTR_ERR(ld);
> + if (IS_ERR(bd)) {
> + ret = PTR_ERR(bd);
> goto out_free_lcd;
> }
>
>
Yes, It's my mistake. It has to be changed as you said.
Thank you,
^ permalink raw reply
* [RFC][PATCH 3/3] sh_mobile_meram: MERAM platform data for LCDC
From: Damian Hobson-Garcia @ 2011-03-29 3:35 UTC (permalink / raw)
To: linux-fbdev
Based on the patch by Takanari Hayama <taki@igel.co.jp>
Add the necessary platform data to add MERAM functionality to LCDC
Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
---
arch/arm/mach-shmobile/board-ap4evb.c | 69 +++++++++++++++++++++++++++++++++
1 files changed, 69 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index a94f29d..e467696 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -249,6 +249,31 @@ static int slot_cn7_get_cd(struct platform_device *pdev)
{
return !gpio_get_value(GPIO_PORT41);
}
+#ifdef CONFIG_FB_SH_MOBILE_MERAM
+/* MERAM */
+static struct sh_mobile_meram_info mackerel_meram_info = {
+ .addr_mode = SH_MOBILE_MERAM_MODE1,
+};
+
+static struct resource meram_resources[] = {
+ [0] = {
+ .name = "MERAM",
+ .start = 0xe8000000,
+ .end = 0xe81fffff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device meram_device = {
+ .name = "sh_mobile_meram",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(meram_resources),
+ .resource = meram_resources,
+ .dev = {
+ .platform_data = &mackerel_meram_info,
+ },
+};
+#endif
/* SH_MMCIF */
static struct resource sh_mmcif_resources[] = {
@@ -431,6 +456,23 @@ const static struct fb_videomode ap4evb_lcdc_modes[] = {
#endif
},
};
+#ifdef CONFIG_FB_SH_MOBILE_MERAM
+static struct sh_mobile_meram_cfg lcd_meram_cfg = {
+ .meram_dev = &mackerel_meram_info,
+ .icb[0] = {
+ .marker_icb = 28,
+ .cache_icb = 24,
+ .meram_offset = 0x0,
+ .meram_size = 0x40,
+ },
+ .icb[1] = {
+ .marker_icb = 29,
+ .cache_icb = 25,
+ .meram_offset = 0x40,
+ .meram_size = 0x40,
+ },
+};
+#endif
static struct sh_mobile_lcdc_info lcdc_info = {
.ch[0] = {
@@ -438,6 +480,9 @@ static struct sh_mobile_lcdc_info lcdc_info = {
.bpp = 16,
.lcd_cfg = ap4evb_lcdc_modes,
.num_cfg = ARRAY_SIZE(ap4evb_lcdc_modes),
+#ifdef CONFIG_FB_SH_MOBILE_MERAM
+ .meram_cfg = &lcd_meram_cfg,
+#endif
}
};
@@ -708,6 +753,23 @@ static struct platform_device fsi_device = {
static struct platform_device fsi_ak4643_device = {
.name = "sh_fsi2_a_ak4643",
};
+#ifdef CONFIG_FB_SH_MOBILE_MERAM
+static struct sh_mobile_meram_cfg hdmi_meram_cfg = {
+ .meram_dev = &mackerel_meram_info,
+ .icb[0] = {
+ .marker_icb = 30,
+ .cache_icb = 26,
+ .meram_offset = 0x80,
+ .meram_size = 0x100,
+ },
+ .icb[1] = {
+ .marker_icb = 31,
+ .cache_icb = 27,
+ .meram_offset = 0x180,
+ .meram_size = 0x100,
+ },
+};
+#endif
static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
.clock_source = LCDC_CLK_EXTERNAL,
@@ -717,6 +779,10 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
.interface_type = RGB24,
.clock_divider = 1,
.flags = LCDC_FLAGS_DWPOL,
+#ifdef CONFIG_FB_SH_MOBILE_MERAM
+ .meram_cfg = &hdmi_meram_cfg,
+#endif
+
}
};
@@ -945,6 +1011,9 @@ static struct platform_device *ap4evb_devices[] __initdata = {
&csi2_device,
&ceu_device,
&ap4evb_camera,
+#ifdef CONFIG_FB_SH_MOBILE_MERAM
+ &meram_device,
+#endif
};
static int __init hdmi_init_pm_clock(void)
--
1.7.1
^ permalink raw reply related
* [RFC][PATCH 2/3] sh_mobile_meram: Add support for NV24 framebuffers
From: Damian Hobson-Garcia @ 2011-03-29 3:35 UTC (permalink / raw)
To: linux-fbdev
Since the NV24 framebuffer has a CbCr plane that is twice as wide
as the Y plane, it needs to be handled as a special case.
Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
---
drivers/video/sh_mobile_lcdcfb.c | 10 +++++++---
drivers/video/sh_mobile_meram.c | 24 +++++++++++++++++++-----
include/video/sh_mobile_meram.h | 3 ++-
3 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 92366bd..6b1db92 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -626,10 +626,14 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
ch->meram_enabled = 0;
- if (ch->info->var.nonstd)
- pf = SH_MOBILE_MERAM_PF_NV;
- else
+ if (ch->info->var.nonstd) {
+ if (ch->info->var.bits_per_pixel = 24)
+ pf = SH_MOBILE_MERAM_PF_NV24;
+ else
+ pf = SH_MOBILE_MERAM_PF_NV;
+ } else {
pf = SH_MOBILE_MERAM_PF_RGB;
+ }
ret = mdev->ops->meram_register(mdev, cfg, pitch,
ch->info->var.yres,
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index bd68f3d..9170c82 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/sh_mobile_meram.c
@@ -164,6 +164,16 @@ static inline void meram_unmark(struct sh_mobile_meram_priv *priv,
}
}
+/*
+ * is this a YCbCr(NV12, NV16 or NV24) colorspace
+ */
+static inline int is_nvcolor(int cspace)
+{
+ if (cspace = SH_MOBILE_MERAM_PF_NV ||
+ cspace = SH_MOBILE_MERAM_PF_NV24)
+ return 1;
+ return 0;
+}
/*
* set the next address to fetch
@@ -184,7 +194,7 @@ static inline void meram_set_next_addr(struct sh_mobile_meram_priv *priv,
meram_write_icb(priv->base, cfg->icb[0].marker_icb, target,
base_addr_y + cfg->icb[0].cache_unit);
- if (cfg->pixelformat = SH_MOBILE_MERAM_PF_NV) {
+ if (is_nvcolor(cfg->pixelformat)) {
meram_write_icb(priv->base, cfg->icb[1].cache_icb, target,
base_addr_c);
meram_write_icb(priv->base, cfg->icb[1].marker_icb, target,
@@ -208,7 +218,7 @@ static inline void meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
icb_offset = 0xc0000000 | (cfg->current_reg << 23);
*icb_addr_y = icb_offset | (cfg->icb[0].marker_icb << 24);
- if ((*icb_addr_c) && cfg->pixelformat = SH_MOBILE_MERAM_PF_NV)
+ if ((*icb_addr_c) && is_nvcolor(cfg->pixelformat))
*icb_addr_c = icb_offset | (cfg->icb[1].marker_icb << 24);
}
@@ -316,6 +326,7 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
return -EINVAL;
if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
+ pixelformat != SH_MOBILE_MERAM_PF_NV24 &&
pixelformat != SH_MOBILE_MERAM_PF_RGB)
return -EINVAL;
@@ -366,7 +377,7 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
n = 2;
}
- if (pixelformat = SH_MOBILE_MERAM_PF_NV && n != 2) {
+ if (is_nvcolor(pixelformat) && n != 2) {
dev_err(&pdev->dev, "requires two ICB sets for planar Y/C.");
error = -EINVAL;
goto err;
@@ -375,7 +386,7 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
/* we now register the ICB */
cfg->pixelformat = pixelformat;
meram_mark(priv, &cfg->icb[0]);
- if (pixelformat = SH_MOBILE_MERAM_PF_NV)
+ if (is_nvcolor(pixelformat))
meram_mark(priv, &cfg->icb[1]);
/* initialize MERAM */
@@ -384,6 +395,9 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
if (pixelformat = SH_MOBILE_MERAM_PF_NV)
meram_init(priv, &cfg->icb[1], xres, (yres + 1) / 2,
&out_pitch);
+ else if (pixelformat = SH_MOBILE_MERAM_PF_NV24)
+ meram_init(priv, &cfg->icb[1], 2 * xres, (yres + 1) / 2,
+ &out_pitch);
cfg->current_reg = 1;
meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c);
@@ -410,7 +424,7 @@ static int sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata,
mutex_lock(&priv->lock);
/* deinit & unmark */
- if (cfg->pixelformat = SH_MOBILE_MERAM_PF_NV) {
+ if (is_nvcolor(cfg->pixelformat)) {
meram_deinit(priv, &cfg->icb[1]);
meram_unmark(priv, &cfg->icb[1]);
}
diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
index e6d2410..989eb23 100644
--- a/include/video/sh_mobile_meram.h
+++ b/include/video/sh_mobile_meram.h
@@ -9,7 +9,8 @@ enum {
enum {
SH_MOBILE_MERAM_PF_NV = 0,
- SH_MOBILE_MERAM_PF_RGB
+ SH_MOBILE_MERAM_PF_RGB,
+ SH_MOBILE_MERAM_PF_NV24
};
--
1.7.1
^ permalink raw reply related
* [RFC][PATCH 1/3] sh_mobile_meram: MERAM framework for LCDC
From: Damian Hobson-Garcia @ 2011-03-29 3:35 UTC (permalink / raw)
To: linux-fbdev
Based on the patch by Takanari Hayama <taki@igel.co.jp>
Adds support framework necessary to use Media RAM (MERAM)
caching functionality with the LCDC. The MERAM is accessed
through up to 4 Interconnect Buffers (ICBs).
ICB numbers and MERAM address ranges to use are specified in
by filling in the .meram_cfg member of the LCDC platform data
Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
---
drivers/video/Kconfig | 12 +
drivers/video/Makefile | 1 +
drivers/video/sh_mobile_lcdcfb.c | 100 +++++++-
drivers/video/sh_mobile_lcdcfb.h | 1 +
drivers/video/sh_mobile_meram.c | 553 ++++++++++++++++++++++++++++++++++++++
drivers/video/sh_mobile_meram.h | 41 +++
include/video/sh_mobile_lcdc.h | 2 +
include/video/sh_mobile_meram.h | 68 +++++
8 files changed, 769 insertions(+), 9 deletions(-)
create mode 100644 drivers/video/sh_mobile_meram.c
create mode 100644 drivers/video/sh_mobile_meram.h
create mode 100644 include/video/sh_mobile_meram.h
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index e6a8d8c..b3f3990 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1975,6 +1975,18 @@ config FB_SH_MOBILE_HDMI
---help---
Driver for the on-chip SH-Mobile HDMI controller.
+config FB_SH_MOBILE_MERAM
+ tristate "SuperH Mobile MERAM read ahead support for LCDC"
+ depends on FB_SH_MOBILE_LCDC
+ default y
+ ---help---
+ Enable MERAM support for the SH-Mobile LCD controller.
+
+ This will allow for caching of the framebuffer to provide more
+ reliable access under heavy main memory bus traffic situations.
+ Up to 4 memory channels can be configured, allowing 4 RGB or
+ 2 YCbCr framebuffers to be configured.
+
config FB_TMIO
tristate "Toshiba Mobile IO FrameBuffer support"
depends on FB && MFD_CORE
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 2ea44b6..8b83129 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -130,6 +130,7 @@ obj-$(CONFIG_FB_UDL) += udlfb.o
obj-$(CONFIG_FB_XILINX) += xilinxfb.o
obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o
obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o
+obj-$(CONFIG_FB_SH_MOBILE_MERAM) += sh_mobile_meram.o
obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
obj-$(CONFIG_FB_OMAP) += omap/
obj-y += omap2/
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 757665b..92366bd 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -27,6 +27,7 @@
#include <asm/atomic.h>
#include "sh_mobile_lcdcfb.h"
+#include "sh_mobile_meram.h"
#define SIDE_B_OFFSET 0x1000
#define MIRROR_OFFSET 0x2000
@@ -564,6 +565,9 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
}
for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
+ unsigned long base_addr_y;
+ unsigned long base_addr_c = 0;
+ int pitch;
ch = &priv->ch[k];
if (!priv->ch[k].enabled)
@@ -598,16 +602,63 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
}
lcdc_write_chan(ch, LDDFR, tmp);
+ base_addr_y = ch->info->fix.smem_start;
+ base_addr_c = base_addr_y +
+ ch->info->var.xres *
+ ch->info->var.yres_virtual;
+ pitch = ch->info->fix.line_length;
+
+ /* test if we can enable meram */
+ if (ch->cfg.meram_cfg) {
+ struct sh_mobile_meram_cfg *cfg;
+ struct sh_mobile_meram_info *mdev;
+ unsigned long icb_addr_y, icb_addr_c;
+ int icb_pitch;
+ int pf;
+
+ cfg = ch->cfg.meram_cfg;
+ mdev = cfg->meram_dev;
+ /* we need to de-init configured ICBs before we
+ * we can re-initialize them.
+ */
+ if (ch->meram_enabled)
+ mdev->ops->meram_unregister(mdev, cfg);
+
+ ch->meram_enabled = 0;
+
+ if (ch->info->var.nonstd)
+ pf = SH_MOBILE_MERAM_PF_NV;
+ else
+ pf = SH_MOBILE_MERAM_PF_RGB;
+
+ ret = mdev->ops->meram_register(mdev, cfg, pitch,
+ ch->info->var.yres,
+ pf,
+ base_addr_y,
+ base_addr_c,
+ &icb_addr_y,
+ &icb_addr_c,
+ &icb_pitch);
+ if (!ret) {
+ /* set LDSA1R value */
+ base_addr_y = icb_addr_y;
+ pitch = icb_pitch;
+
+ /* set LDSA2R value if required */
+ if (base_addr_c)
+ base_addr_c = icb_addr_c;
+
+ ch->meram_enabled = 1;
+ }
+ }
+
/* point out our frame buffer */
- lcdc_write_chan(ch, LDSA1R, ch->info->fix.smem_start);
+ lcdc_write_chan(ch, LDSA1R, base_addr_y);
if (ch->info->var.nonstd)
- lcdc_write_chan(ch, LDSA2R,
- ch->info->fix.smem_start +
- ch->info->var.xres *
- ch->info->var.yres_virtual);
+ lcdc_write_chan(ch, LDSA2R, base_addr_c);
/* set line size */
- lcdc_write_chan(ch, LDMLSR, ch->info->fix.line_length);
+ lcdc_write_chan(ch, LDMLSR, pitch);
/* setup deferred io if SYS bus */
tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
@@ -692,6 +743,17 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
board_cfg->display_off(board_cfg->board_data);
module_put(board_cfg->owner);
}
+
+ /* disable the meram */
+ if (ch->meram_enabled) {
+ struct sh_mobile_meram_cfg *cfg;
+ struct sh_mobile_meram_info *mdev;
+ cfg = ch->cfg.meram_cfg;
+ mdev = cfg->meram_dev;
+ mdev->ops->meram_unregister(mdev, cfg);
+ ch->meram_enabled = 0;
+ }
+
}
/* stop the lcdc */
@@ -875,9 +937,29 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
} else
base_addr_c = 0;
- lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
- if (base_addr_c)
- lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
+ if (!ch->meram_enabled) {
+ lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
+ if (base_addr_c)
+ lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
+ } else {
+ struct sh_mobile_meram_cfg *cfg;
+ struct sh_mobile_meram_info *mdev;
+ unsigned long icb_addr_y, icb_addr_c;
+ int ret;
+
+ cfg = ch->cfg.meram_cfg;
+ mdev = cfg->meram_dev;
+ ret = mdev->ops->meram_update(mdev, cfg,
+ base_addr_y, base_addr_c,
+ &icb_addr_y, &icb_addr_c);
+ if (ret)
+ return ret;
+
+ lcdc_write_chan_mirror(ch, LDSA1R, icb_addr_y);
+ if (icb_addr_c)
+ lcdc_write_chan_mirror(ch, LDSA2R, icb_addr_c);
+
+ }
if (lcdc_chan_is_sublcd(ch))
lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index 4635eed..d6d9f37 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -38,6 +38,7 @@ struct sh_mobile_lcdc_chan {
struct fb_var_screeninfo display_var;
int use_count;
struct mutex open_lock; /* protects the use counter */
+ int meram_enabled;
};
#endif
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
new file mode 100644
index 0000000..bd68f3d
--- /dev/null
+++ b/drivers/video/sh_mobile_meram.c
@@ -0,0 +1,553 @@
+/*
+ * SuperH Mobile MERAM Driver for SuperH Mobile LCDC Driver
+ *
+ * Copyright (c) 2011 Damian Hobson-Garcia <dhobsong@igel.co.jp>
+ * Takanari Hayama <taki@igel.co.jp>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include "sh_mobile_meram.h"
+
+/* meram registers */
+#define MExxCTL 0x0
+#define MExxBSIZE 0x4
+#define MExxMNCF 0x8
+#define MExxSARA 0x10
+#define MExxSARB 0x14
+#define MExxSBSIZE 0x18
+
+#define MERAM_MExxCTL_VAL(ctl, next_icb, addr) \
+ ((ctl) | (((next_icb) & 0x1f) << 11) | (((addr) & 0x7ff) << 16))
+#define MERAM_MExxBSIZE_VAL(a, b, c) \
+ (((a) << 28) | ((b) << 16) | (c))
+
+#define MEVCR1 0x4
+#define MEACTS 0x10
+#define MEQSEL1 0x40
+#define MEQSEL2 0x44
+
+/* settings */
+#define MERAM_SEC_LINE 15
+#define MERAM_LINE_WIDTH 2048
+
+/*
+ * MERAM/ICB access functions
+ */
+
+#define MERAM_ICB_OFFSET(base, idx, off) \
+ ((base) + (0x400 + ((idx) * 0x20) + (off)))
+
+static inline void meram_write_icb(void __iomem *base, int idx, int off,
+ unsigned long val)
+{
+ iowrite32(val, MERAM_ICB_OFFSET(base, idx, off));
+}
+
+static inline unsigned long meram_read_icb(void __iomem *base, int idx, int off)
+{
+ return ioread32(MERAM_ICB_OFFSET(base, idx, off));
+}
+
+static inline void meram_write_reg(void __iomem *base, int off,
+ unsigned long val)
+{
+ iowrite32(val, base + off);
+}
+
+static inline unsigned long meram_read_reg(void __iomem *base, int off)
+{
+ return ioread32(base + off);
+}
+
+/*
+ * register ICB
+ */
+
+#define MERAM_CACHE_START(p) ((p) >> 16)
+#define MERAM_CACHE_END(p) ((p) & 0xffff)
+#define MERAM_CACHE_SET(o, s) ((((o) & 0xffff) << 16) | \
+ (((o) + (s) - 1) & 0xffff))
+
+/*
+ * check if there's no overlaps in MERAM allocation.
+ */
+
+static inline int meram_check_overlap(struct sh_mobile_meram_priv *priv,
+ struct sh_mobile_meram_icb *new)
+{
+ int i;
+ int used_start, used_end, meram_start, meram_end;
+
+ /* valid ICB? */
+ if (new->marker_icb & ~0x1f || new->cache_icb & ~0x1f)
+ return 1;
+
+ if (test_bit(new->marker_icb, &priv->used_icb) ||
+ test_bit(new->cache_icb, &priv->used_icb))
+ return 1;
+
+ for (i = 0; i < priv->used_meram_cache_regions; i++) {
+ used_start = MERAM_CACHE_START(priv->used_meram_cache[i]);
+ used_end = MERAM_CACHE_END(priv->used_meram_cache[i]);
+ meram_start = new->meram_offset;
+ meram_end = new->meram_offset + new->meram_size;
+
+ if ((meram_start >= used_start && meram_start < used_end) ||
+ (meram_end > used_start && meram_end < used_end))
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * mark the specified ICB as used
+ */
+
+static inline void meram_mark(struct sh_mobile_meram_priv *priv,
+ struct sh_mobile_meram_icb *new)
+{
+ int n;
+
+ if (new->marker_icb < 0 || new->cache_icb < 0)
+ return;
+
+ __set_bit(new->marker_icb, &priv->used_icb);
+ __set_bit(new->cache_icb, &priv->used_icb);
+
+ n = priv->used_meram_cache_regions;
+
+ priv->used_meram_cache[n] = MERAM_CACHE_SET(new->meram_offset,
+ new->meram_size);
+
+ priv->used_meram_cache_regions++;
+}
+
+/*
+ * unmark the specified ICB as used
+ */
+
+static inline void meram_unmark(struct sh_mobile_meram_priv *priv,
+ struct sh_mobile_meram_icb *icb)
+{
+ int i;
+ unsigned long pattern;
+
+ if (icb->marker_icb < 0 || icb->cache_icb < 0)
+ return;
+
+ __clear_bit(icb->marker_icb, &priv->used_icb);
+ __clear_bit(icb->cache_icb, &priv->used_icb);
+
+ pattern = MERAM_CACHE_SET(icb->meram_offset, icb->meram_size);
+ for (i = 0; i < priv->used_meram_cache_regions; i++) {
+ if (priv->used_meram_cache[i] = pattern) {
+ while (i < priv->used_meram_cache_regions - 1) {
+ priv->used_meram_cache[i] + priv->used_meram_cache[i + 1] ;
+ i++;
+ }
+ priv->used_meram_cache[i] = 0;
+ priv->used_meram_cache_regions--;
+ break;
+ }
+ }
+}
+
+
+/*
+ * set the next address to fetch
+ */
+static inline void meram_set_next_addr(struct sh_mobile_meram_priv *priv,
+ struct sh_mobile_meram_cfg *cfg,
+ unsigned long base_addr_y,
+ unsigned long base_addr_c)
+{
+ unsigned long target;
+
+ target = (cfg->current_reg) ? MExxSARA : MExxSARB;
+ cfg->current_reg ^= 1;
+
+ /* set the next address to fetch */
+ meram_write_icb(priv->base, cfg->icb[0].cache_icb, target,
+ base_addr_y);
+ meram_write_icb(priv->base, cfg->icb[0].marker_icb, target,
+ base_addr_y + cfg->icb[0].cache_unit);
+
+ if (cfg->pixelformat = SH_MOBILE_MERAM_PF_NV) {
+ meram_write_icb(priv->base, cfg->icb[1].cache_icb, target,
+ base_addr_c);
+ meram_write_icb(priv->base, cfg->icb[1].marker_icb, target,
+ base_addr_c + cfg->icb[1].cache_unit);
+ }
+}
+
+/*
+ * get the next ICB address
+ */
+static inline void meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
+ struct sh_mobile_meram_cfg *cfg,
+ unsigned long *icb_addr_y,
+ unsigned long *icb_addr_c)
+{
+ unsigned long icb_offset;
+
+ if (pdata->addr_mode = SH_MOBILE_MERAM_MODE0)
+ icb_offset = 0x80000000 | (cfg->current_reg << 29);
+ else
+ icb_offset = 0xc0000000 | (cfg->current_reg << 23);
+
+ *icb_addr_y = icb_offset | (cfg->icb[0].marker_icb << 24);
+ if ((*icb_addr_c) && cfg->pixelformat = SH_MOBILE_MERAM_PF_NV)
+ *icb_addr_c = icb_offset | (cfg->icb[1].marker_icb << 24);
+}
+
+#define MERAM_CALC_BYTECOUNT(x, y) \
+ (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1))
+
+/*
+ * initialize MERAM
+ */
+
+static int meram_init(struct sh_mobile_meram_priv *priv,
+ struct sh_mobile_meram_icb *icb,
+ int xres, int yres, int *out_pitch)
+{
+ unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres);
+ unsigned long bnm;
+ int lcdc_pitch, xpitch, line_cnt;
+ int save_lines;
+
+ /* adjust pitch to 1024, 2048, 4096 or 8192 */
+ lcdc_pitch = (xres - 1) | 1023;
+ lcdc_pitch = lcdc_pitch | (lcdc_pitch >> 1);
+ lcdc_pitch = lcdc_pitch | (lcdc_pitch >> 2);
+ lcdc_pitch += 1;
+
+ /* derive settings */
+ if (lcdc_pitch = 8192 && yres >= 1024) {
+ lcdc_pitch = xpitch = MERAM_LINE_WIDTH;
+ line_cnt = total_byte_count >> 11;
+ *out_pitch = xres;
+ save_lines = (icb->meram_size / 16 / MERAM_SEC_LINE);
+ save_lines *= MERAM_SEC_LINE;
+ } else {
+ xpitch = xres;
+ line_cnt = yres;
+ *out_pitch = lcdc_pitch;
+ save_lines = icb->meram_size / (lcdc_pitch >> 10) / 2;
+ save_lines &= 0xff;
+ }
+ bnm = (save_lines - 1) << 16;
+
+ /* TODO: we better to check if we have enough MERAM buffer size */
+
+ /* set up ICB */
+ meram_write_icb(priv->base, icb->cache_icb, MExxBSIZE,
+ MERAM_MExxBSIZE_VAL(0x0, line_cnt - 1, xpitch - 1));
+ meram_write_icb(priv->base, icb->marker_icb, MExxBSIZE,
+ MERAM_MExxBSIZE_VAL(0xf, line_cnt - 1, xpitch - 1));
+
+ meram_write_icb(priv->base, icb->cache_icb, MExxMNCF, bnm);
+ meram_write_icb(priv->base, icb->marker_icb, MExxMNCF, bnm);
+
+ meram_write_icb(priv->base, icb->cache_icb, MExxSBSIZE, xpitch);
+ meram_write_icb(priv->base, icb->marker_icb, MExxSBSIZE, xpitch);
+
+ /* save a cache unit size */
+ icb->cache_unit = xres * save_lines;
+
+ /*
+ * Set MERAM for framebuffer
+ *
+ * 0x70f: WD = 0x3, WS=0x1, CM=0x1, MDû mode
+ * we also chain the cache_icb and the marker_icb.
+ * we also split the allocated MERAM buffer between two ICBs.
+ */
+ meram_write_icb(priv->base, icb->cache_icb, MExxCTL,
+ MERAM_MExxCTL_VAL(0x70f, icb->marker_icb,
+ icb->meram_offset));
+ meram_write_icb(priv->base, icb->marker_icb, MExxCTL,
+ MERAM_MExxCTL_VAL(0x70f, icb->cache_icb,
+ icb->meram_offset +
+ icb->meram_size / 2));
+
+ return 0;
+}
+
+static void meram_deinit(struct sh_mobile_meram_priv *priv,
+ struct sh_mobile_meram_icb *icb)
+{
+ /* disable ICB */
+ meram_write_icb(priv->base, icb->cache_icb, MExxCTL, 0);
+ meram_write_icb(priv->base, icb->marker_icb, MExxCTL, 0);
+ icb->cache_unit = 0;
+}
+
+/*
+ * register the ICB
+ */
+
+static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
+ struct sh_mobile_meram_cfg *cfg,
+ int xres, int yres, int pixelformat,
+ unsigned long base_addr_y,
+ unsigned long base_addr_c,
+ unsigned long *icb_addr_y,
+ unsigned long *icb_addr_c,
+ int *pitch)
+{
+ struct platform_device *pdev;
+ struct sh_mobile_meram_priv *priv;
+ int n, out_pitch;
+ int error = 0;
+
+ if (!pdata || !pdata->priv || !pdata->pdev || !cfg)
+ return -EINVAL;
+
+ if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
+ pixelformat != SH_MOBILE_MERAM_PF_RGB)
+ return -EINVAL;
+
+ priv = pdata->priv;
+ pdev = pdata->pdev;
+
+ dev_dbg(&pdev->dev, "registering %dx%d (%s) (y=%08lx, c=%08lx)",
+ xres, yres, (!pixelformat) ? "yuv" : "rgb",
+ base_addr_y, base_addr_c);
+
+ mutex_lock(&priv->lock);
+
+ /* we can't handle wider than 8192px */
+ if (xres > 8192) {
+ dev_err(&pdev->dev, "width exceeding the limit (> 8192).");
+ error = -EINVAL;
+ goto err;
+ }
+
+ if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) {
+ dev_err(&pdev->dev, "no more ICB available.");
+ error = -EINVAL;
+ goto err;
+ }
+
+ /* do we have at least one ICB config? */
+ if (cfg->icb[0].marker_icb < 0 || cfg->icb[0].cache_icb < 0) {
+ dev_err(&pdev->dev, "at least one ICB is required.");
+ error = -EINVAL;
+ goto err;
+ }
+
+ /* make sure that there's no overlaps */
+ if (meram_check_overlap(priv, &cfg->icb[0])) {
+ dev_err(&pdev->dev, "conflicting config detected.");
+ error = -EINVAL;
+ goto err;
+ }
+ n = 1;
+
+ /* do the same if we have the second ICB set */
+ if (cfg->icb[1].marker_icb >= 0 && cfg->icb[1].cache_icb >= 0) {
+ if (meram_check_overlap(priv, &cfg->icb[1])) {
+ dev_err(&pdev->dev, "conflicting config detected.");
+ error = -EINVAL;
+ goto err;
+ }
+ n = 2;
+ }
+
+ if (pixelformat = SH_MOBILE_MERAM_PF_NV && n != 2) {
+ dev_err(&pdev->dev, "requires two ICB sets for planar Y/C.");
+ error = -EINVAL;
+ goto err;
+ }
+
+ /* we now register the ICB */
+ cfg->pixelformat = pixelformat;
+ meram_mark(priv, &cfg->icb[0]);
+ if (pixelformat = SH_MOBILE_MERAM_PF_NV)
+ meram_mark(priv, &cfg->icb[1]);
+
+ /* initialize MERAM */
+ meram_init(priv, &cfg->icb[0], xres, yres, &out_pitch);
+ *pitch = out_pitch;
+ if (pixelformat = SH_MOBILE_MERAM_PF_NV)
+ meram_init(priv, &cfg->icb[1], xres, (yres + 1) / 2,
+ &out_pitch);
+
+ cfg->current_reg = 1;
+ meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c);
+ meram_get_next_icb_addr(pdata, cfg, icb_addr_y, icb_addr_c);
+
+ dev_dbg(&pdev->dev, "registered - can access via y=%08lx, c=%08lx",
+ *icb_addr_y, *icb_addr_c);
+
+err:
+ mutex_unlock(&priv->lock);
+ return error;
+}
+
+static int sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata,
+ struct sh_mobile_meram_cfg *cfg)
+{
+ struct sh_mobile_meram_priv *priv;
+
+ if (!pdata || !pdata->priv || !cfg)
+ return -EINVAL;
+
+ priv = pdata->priv;
+
+ mutex_lock(&priv->lock);
+
+ /* deinit & unmark */
+ if (cfg->pixelformat = SH_MOBILE_MERAM_PF_NV) {
+ meram_deinit(priv, &cfg->icb[1]);
+ meram_unmark(priv, &cfg->icb[1]);
+ }
+ meram_deinit(priv, &cfg->icb[0]);
+ meram_unmark(priv, &cfg->icb[0]);
+
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static int sh_mobile_meram_update(struct sh_mobile_meram_info *pdata,
+ struct sh_mobile_meram_cfg *cfg,
+ unsigned long base_addr_y,
+ unsigned long base_addr_c,
+ unsigned long *icb_addr_y,
+ unsigned long *icb_addr_c)
+{
+ struct sh_mobile_meram_priv *priv;
+
+ if (!pdata || !pdata->priv || !cfg)
+ return -EINVAL;
+
+ priv = pdata->priv;
+
+ mutex_lock(&priv->lock);
+
+ meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c);
+ meram_get_next_icb_addr(pdata, cfg, icb_addr_y, icb_addr_c);
+
+ mutex_unlock(&priv->lock);
+
+ return 0;
+}
+
+static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
+ .module = THIS_MODULE,
+ .meram_register = sh_mobile_meram_register,
+ .meram_unregister = sh_mobile_meram_unregister,
+ .meram_update = sh_mobile_meram_update,
+};
+
+/*
+ * initialize MERAM
+ */
+
+static int sh_mobile_meram_remove(struct platform_device *pdev);
+
+static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
+{
+ struct sh_mobile_meram_priv *priv;
+ struct sh_mobile_meram_info *pdata = pdev->dev.platform_data;
+ struct resource *res;
+ int error;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "no platform data defined\n");
+ return -EINVAL;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "cannot get platform resources\n");
+ return -ENOENT;
+ }
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(&pdev->dev, "cannot allocate device data\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, priv);
+
+ /* initialize private data */
+ mutex_init(&priv->lock);
+ priv->base = ioremap_nocache(res->start, resource_size(res));
+ if (!priv->base) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ error = -EFAULT;
+ goto err;
+ }
+ pdata->ops = &sh_mobile_meram_ops;
+ pdata->priv = priv;
+ pdata->pdev = pdev;
+
+ /* initialize ICB addressing mode */
+ if (pdata->addr_mode = SH_MOBILE_MERAM_MODE1)
+ meram_write_reg(priv->base, MEVCR1, 1 << 29);
+
+ dev_info(&pdev->dev, "sh_mobile_meram initialized.");
+
+ return 0;
+
+err:
+ sh_mobile_meram_remove(pdev);
+
+ return error;
+}
+
+
+static int sh_mobile_meram_remove(struct platform_device *pdev)
+{
+ struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
+
+ if (priv->base)
+ iounmap(priv->base);
+
+ mutex_destroy(&priv->lock);
+
+ kfree(priv);
+
+ return 0;
+}
+
+static struct platform_driver sh_mobile_meram_driver = {
+ .driver = {
+ .name = "sh_mobile_meram",
+ .owner = THIS_MODULE,
+ },
+ .probe = sh_mobile_meram_probe,
+ .remove = sh_mobile_meram_remove,
+};
+
+static int __init sh_mobile_meram_init(void)
+{
+ return platform_driver_register(&sh_mobile_meram_driver);
+}
+
+static void __exit sh_mobile_meram_exit(void)
+{
+ platform_driver_unregister(&sh_mobile_meram_driver);
+}
+
+module_init(sh_mobile_meram_init);
+module_exit(sh_mobile_meram_exit);
+
+MODULE_DESCRIPTION("SuperH Mobile MERAM driver");
+MODULE_AUTHOR("Damian Hobson-Garcia / Takanari Hayama");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/sh_mobile_meram.h b/drivers/video/sh_mobile_meram.h
new file mode 100644
index 0000000..82c54fb
--- /dev/null
+++ b/drivers/video/sh_mobile_meram.h
@@ -0,0 +1,41 @@
+#ifndef __sh_mobile_meram_h__
+#define __sh_mobile_meram_h__
+
+#include <linux/mutex.h>
+#include <video/sh_mobile_meram.h>
+
+/*
+ * MERAM private
+ */
+
+#define MERAM_ICB_Y 0x1
+#define MERAM_ICB_C 0x2
+
+/* MERAM cache size */
+#define SH_MOBILE_MERAM_ICB_NUM 32
+
+#define SH_MOBILE_MERAM_CACHE_OFFSET(p) ((p) >> 16)
+#define SH_MOBILE_MERAM_CACHE_SIZE(p) ((p) & 0xffff)
+
+struct sh_mobile_meram_priv {
+ void __iomem *base;
+ struct mutex lock;
+ unsigned long used_icb;
+ int used_meram_cache_regions;
+ unsigned long used_meram_cache[SH_MOBILE_MERAM_ICB_NUM];
+};
+
+int sh_mobile_meram_alloc_icb(const struct sh_mobile_meram_cfg *cfg,
+ int xres,
+ int yres,
+ unsigned int base_addr,
+ int yuv_mode,
+ int *marker_icb,
+ int *out_pitch);
+
+void sh_mobile_meram_free_icb(int marker_icb);
+
+#define SH_MOBILE_MERAM_START(ind, ab) \
+ (0xC0000000 | ((ab & 0x1) << 23) | ((ind & 0x1F) << 24))
+
+#endif /* !__sh_mobile_meram_h__ */
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h
index 2c8d369..7d07ac8 100644
--- a/include/video/sh_mobile_lcdc.h
+++ b/include/video/sh_mobile_lcdc.h
@@ -2,6 +2,7 @@
#define __ASM_SH_MOBILE_LCDC_H__
#include <linux/fb.h>
+#include <video/sh_mobile_meram.h>
enum {
RGB8, /* 24bpp, 8:8:8 */
@@ -87,6 +88,7 @@ struct sh_mobile_lcdc_chan_cfg {
struct sh_mobile_lcdc_bl_info bl_info;
struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */
int nonstd;
+ struct sh_mobile_meram_cfg *meram_cfg;
};
struct sh_mobile_lcdc_info {
diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
new file mode 100644
index 0000000..e6d2410
--- /dev/null
+++ b/include/video/sh_mobile_meram.h
@@ -0,0 +1,68 @@
+#ifndef __VIDEO_SH_MOBILE_MERAM_H__
+#define __VIDEO_SH_MOBILE_MERAM_H__
+
+/* For sh_mobile_meram_info.addr_mode */
+enum {
+ SH_MOBILE_MERAM_MODE0 = 0,
+ SH_MOBILE_MERAM_MODE1
+};
+
+enum {
+ SH_MOBILE_MERAM_PF_NV = 0,
+ SH_MOBILE_MERAM_PF_RGB
+};
+
+
+struct sh_mobile_meram_priv;
+struct sh_mobile_meram_ops;
+
+struct sh_mobile_meram_info {
+ int addr_mode;
+ struct sh_mobile_meram_ops *ops;
+ struct sh_mobile_meram_priv *priv;
+ struct platform_device *pdev;
+};
+
+/* icb config */
+struct sh_mobile_meram_icb {
+ int marker_icb; /* ICB # for Marker ICB */
+ int cache_icb; /* ICB # for Cache ICB */
+ int meram_offset; /* MERAM Buffer Offset to use */
+ int meram_size; /* MERAM Buffer Size to use */
+
+ int cache_unit; /* bytes to cache per ICB */
+};
+
+struct sh_mobile_meram_cfg {
+ struct sh_mobile_meram_info *meram_dev;
+ struct sh_mobile_meram_icb icb[2];
+ int pixelformat;
+ int current_reg;
+};
+
+struct module;
+struct sh_mobile_meram_ops {
+ struct module *module;
+ /* register usage of meram */
+ int (*meram_register)(struct sh_mobile_meram_info *meram_dev,
+ struct sh_mobile_meram_cfg *cfg,
+ int xres, int yres, int pixelformat,
+ unsigned long base_addr_y,
+ unsigned long base_addr_c,
+ unsigned long *icb_addr_y,
+ unsigned long *icb_addr_c, int *pitch);
+
+ /* unregister usage of meram */
+ int (*meram_unregister)(struct sh_mobile_meram_info *meram_dev,
+ struct sh_mobile_meram_cfg *cfg);
+
+ /* update meram settings */
+ int (*meram_update)(struct sh_mobile_meram_info *meram_dev,
+ struct sh_mobile_meram_cfg *cfg,
+ unsigned long base_addr_y,
+ unsigned long base_addr_c,
+ unsigned long *icb_addr_y,
+ unsigned long *icb_addr_c);
+};
+
+#endif /* __VIDEO_SH_MOBILE_MERAM_H__ */
--
1.7.1
^ permalink raw reply related
* [RFC][PATCH 0/3] MERAM support for LCDC
From: Damian Hobson-Garcia @ 2011-03-29 3:35 UTC (permalink / raw)
To: linux-fbdev
This patch series is based on the fbdev tree.
This series adds support for read-ahead cache access through the ICBs and
MERAM available on SH devices. The exact ICBs to use are chip specific
and are specified in the platform data.
Damian Hobson-Garcia (3):
sh_mobile_meram: MERAM framework for LCDC
sh_mobile_meram: Add support for NV24 framebuffers
sh_mobile_meram: MERAM platform data for LCDC
arch/arm/mach-shmobile/board-ap4evb.c | 69 ++++
drivers/video/Kconfig | 12 +
drivers/video/Makefile | 1 +
drivers/video/sh_mobile_lcdcfb.c | 104 ++++++-
drivers/video/sh_mobile_lcdcfb.h | 1 +
drivers/video/sh_mobile_meram.c | 567 +++++++++++++++++++++++++++++++++
drivers/video/sh_mobile_meram.h | 41 +++
include/video/sh_mobile_lcdc.h | 2 +
include/video/sh_mobile_meram.h | 69 ++++
9 files changed, 857 insertions(+), 9 deletions(-)
create mode 100644 drivers/video/sh_mobile_meram.c
create mode 100644 drivers/video/sh_mobile_meram.h
create mode 100644 include/video/sh_mobile_meram.h
^ permalink raw reply
* Re: [PATCH] fbcon: Remove unused 'display *p' variable from fb_flashcursor()
From: Paul Mundt @ 2011-03-29 3:32 UTC (permalink / raw)
To: Jesse Barnes
Cc: Sergey Senozhatsky, Andrew Morton, Dave Airlie, linux-fbdev,
linux-kernel
In-Reply-To: <20110328091846.485dfef0@jbarnes-desktop>
On Mon, Mar 28, 2011 at 09:18:46AM -0700, Jesse Barnes wrote:
> On Thu, 24 Mar 2011 22:50:52 +0200
> Sergey Senozhatsky <sergey.senozhatsky@gmail.com> wrote:
>
> > fbcon: Remove unused 'display *p' variable from fb_flashcursor()
> >
> > Signed-of-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
> >
>
> Looks fine to me, is Paul the lucky owner of fbdev now?
>
Seems so. I'll roll the patch in with the next batch of fixes.
^ permalink raw reply
* [patch] backlight/pcf50633: check for NULL consistently in
From: Dan Carpenter @ 2011-03-29 3:20 UTC (permalink / raw)
To: linux-fbdev
We checked "pdata" for NULL at the start of the function so we should
check it here as well.
Signed-off-by: Dan Carpenter <error27@gmail.com>
---
Compile tested only. Please review.
diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c
index ef5628d..0fe934f 100644
--- a/drivers/video/backlight/pcf50633-backlight.c
+++ b/drivers/video/backlight/pcf50633-backlight.c
@@ -136,7 +136,9 @@ static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, pcf_bl);
- pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM, pdata->ramp_time);
+ if (pdata)
+ pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM,
+ pdata->ramp_time);
/* Should be different from bl_props.brightness, so we do not exit
* update_status early the first time it's called */
^ permalink raw reply related
* [patch] backlight/ld9040.c: testing the wrong variable in
From: Dan Carpenter @ 2011-03-29 3:19 UTC (permalink / raw)
To: linux-fbdev
We should be testing "bd" here instead of "ld". It's a copy and
paste bug.
Signed-off-by: Dan Carpenter <error27@gmail.com>
diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c
index 7281b25..9e81d69 100644
--- a/drivers/video/backlight/ld9040.c
+++ b/drivers/video/backlight/ld9040.c
@@ -701,8 +701,8 @@ static int ld9040_probe(struct spi_device *spi)
bd = backlight_device_register("ld9040-bl", &spi->dev,
lcd, &ld9040_backlight_ops, NULL);
- if (IS_ERR(ld)) {
- ret = PTR_ERR(ld);
+ if (IS_ERR(bd)) {
+ ret = PTR_ERR(bd);
goto out_free_lcd;
}
^ permalink raw reply related
* Re: [GIT PULL] omap display subsystem changes for 2.6.39
From: Tony Lindgren @ 2011-03-28 21:07 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Felipe Contreras, Paul Mundt, linux-fbdev@vger.kernel.org,
linux-omap@vger.kernel.org
In-Reply-To: <1300866362.2613.5.camel@deskari>
* Tomi Valkeinen <tomi.valkeinen@ti.com> [110323 00:43]:
> On Tue, 2011-03-22 at 13:49 -0500, Felipe Contreras wrote:
> > On Mon, Mar 21, 2011 at 11:51 AM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
> > > Here are OMAP display subsystem patches for 2.6.39 merge window. Quite a
> > > bit of them, and many changes also in arch/arm/mach-omap2, which
> > > unfortunately couldn't go through Tony's linux-omap tree due to
> > > dependencies on DSS driver code.
> >
> > What about this one?
> > http://article.gmane.org/gmane.linux.ports.arm.omap/44975
>
> I seem to have missed that one. But I think that should go through
> Tony's tree to avoid conflicts. Tony?
>
> Acked-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Seems OK for -rc cycle.
Tony
^ permalink raw reply
* Re: [PATCH] fbcon: Remove unused 'display *p' variable from
From: Jesse Barnes @ 2011-03-28 16:18 UTC (permalink / raw)
To: Sergey Senozhatsky
Cc: Paul Mundt, Andrew Morton, Dave Airlie, linux-fbdev, linux-kernel
In-Reply-To: <20110324205052.GA4238@swordfish>
On Thu, 24 Mar 2011 22:50:52 +0200
Sergey Senozhatsky <sergey.senozhatsky@gmail.com> wrote:
> fbcon: Remove unused 'display *p' variable from fb_flashcursor()
>
> Signed-of-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
>
> ---
>
> drivers/video/console/fbcon.c | 2 --
> 1 files changed, 0 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
> index c583934..8745637 100644
> --- a/drivers/video/console/fbcon.c
> +++ b/drivers/video/console/fbcon.c
> @@ -370,7 +370,6 @@ static void fb_flashcursor(struct work_struct *work)
> {
> struct fb_info *info = container_of(work, struct fb_info, queue);
> struct fbcon_ops *ops = info->fbcon_par;
> - struct display *p;
> struct vc_data *vc = NULL;
> int c;
> int mode;
> @@ -386,7 +385,6 @@ static void fb_flashcursor(struct work_struct *work)
> return;
> }
>
> - p = &fb_display[vc->vc_num];
> c = scr_readw((u16 *) vc->vc_pos);
> mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
> CM_ERASE : CM_DRAW;
Looks fine to me, is Paul the lucky owner of fbdev now?
--
Jesse Barnes, Intel Open Source Technology Center
^ permalink raw reply
* vt & fbcon changes
From: Bruno Prémont @ 2011-03-28 14:38 UTC (permalink / raw)
To: linux-fbdev
Hi James,
How is your refactoring of vt (and fbcon) progressing?
Last commit visible in your GIT tree [1] dates back to last November...
I'm looking at resuming my ref-counted framebuffer work though would
like to avoid duplicate work with your vt changes (and/or big merging
conflicts).
From first glance registered_fb[] is the biggest source of conflict,
in your patches you are dropping (most) of its use as you kill con2fb_map[]
in fbcon.c -- on my side I am planning to convert con2fb_map from char
to struct fb_info*
Thanks,
Bruno
[1] http://git.infradead.org/users/jsimmons/linuxconsole-2.6.git
^ permalink raw reply
* Re: [RFC PATCH] HDMI:Support for EDID parsing in kernel.
From: K, Mythri P @ 2011-03-25 15:33 UTC (permalink / raw)
To: Florian Tobias Schandinat
Cc: Corbin Simpson, Jesse Barnes, linux-fbdev, linux-omap, dri-devel,
linux-media
In-Reply-To: <4D8BC915.60400@gmx.de>
Hi Florian,
<snip>
>
>> So why should this be a common library? Most kernel code doesn't need
>> it. Or is there a serious need for video input to parse EDIDs?
>
> It's true that most kernel code does not need it as it is only useful for
> display output systems (and only the ones that can be connected to something
> sending EDID data) but it would be good anyway.
> Because sharing code that should fulfill the same purpose is always a good
> idea. But of course only if the scope is clearly limited as we don't want to
> end up with a mess that nobody dares touching again as it became to complex.
> So I totally agree that we should share the common stuff we all need and
> adding the extras one needs in the subsystem/driver.
> This is good because it looks like we'll have 3 display subsystems within
> the kernel for a long future and with a common library the same patch would
> not need to be done 3 times but only once. Or even more often if drivers
> have there private EDID implementation which I just throw out of mine to
> replace it later with a common one.
>
Precisely my point . Also if there are some bad TV models which
doesn't adhere to standard EDID, It would help to add quirks.
Anyone out there want to help me split the DRM code ? As i don't want
DRMer's to fret over changed code :).
Thanks and regards,
Mythri.
> Regards,
>
> Florian Tobias Schandinat
>
^ permalink raw reply
* Re: [RFC PATCH] HDMI:Support for EDID parsing in kernel.
From: K, Mythri P @ 2011-03-25 13:46 UTC (permalink / raw)
To: Guennadi Liakhovetski
Cc: Jesse Barnes, Dave Airlie, linux-fbdev, linux-omap, dri-devel,
linux-media
In-Reply-To: <Pine.LNX.4.64.1103242001460.21914@axis700.grange>
Hi Gunnedi,
<snip>
>> > Dave's point is that we can't ditch the existing code without
>> > introducing a lot of risk; it would be better to start a library-ized
>> > EDID codebase from the most complete one we have already, i.e. the DRM
>> > EDID code.
>
> Does the DRM EDID-parser also process blocks beyond the first one and
> also parses SVD entries similar to what I've recently added to fbdev? Yes,
> we definitely need a common EDID parses, and maybe we'll have to collect
> various pieces from different implementations.
>
As far as I know , it does not parse SVD ,But it should not be that
difficult to add.
We could take the SVD parsing from your code . In the RFC i have
posted I parse for detailed timing and other VSDB blocks.
Also the parsing should be based on the extension type for multiple
128 byte blocks.
Thanks and regards,
Mythri.
> Thanks
> Guennadi
>
^ permalink raw reply
* Re: [GIT PULL] viafb fixes for 2.6.39
From: Paul Mundt @ 2011-03-24 22:53 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <4D89E6B5.8080005@gmx.de>
On Wed, Mar 23, 2011 at 01:25:25PM +0100, Florian Tobias Schandinat wrote:
> please pull the viafb fixes below.
> They fix the handling of refresh rates which should now work (or at least
> work much better than it did before). Especially the initial refresh rate
> as passed in via module parameter is now handled correct. Before these
> patches this didn't work for higher refresh rates.
>
Pulled, thanks.
^ permalink raw reply
* Re: [PATCH 0/2] Fix resource size miscalculations
From: Joe Perches @ 2011-03-24 22:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1300909445.git.joe@perches.com>
On Wed, 2011-03-23 at 12:55 -0700, Joe Perches wrote:
> Use resource_size a few places
Perhaps this relatively common error is too common.
It seems to be poor style. A possible better style for
struct resource uses could be inline function(s) like:
static inline void __iomem *resource_ioremap(struct resource *r)
{
return ioremap(r->start, resource_size(r));
}
and maybe
static inline struct resource *
resource_request_region(struct resource *r, const char *name)
{
return __request_region(&ioport_resource, r->start, resource_size(r), name, 0);
}
^ permalink raw reply
* Re: [RFC PATCH] HDMI:Support for EDID parsing in kernel.
From: Florian Tobias Schandinat @ 2011-03-24 22:43 UTC (permalink / raw)
To: Corbin Simpson
Cc: K, Mythri P, Jesse Barnes, linux-fbdev, linux-omap, dri-devel,
linux-media
In-Reply-To: <AANLkTi=Yc0Pg9uCZcTei45PLbERutoRc7XyoFghwS=KV@mail.gmail.com>
Corbin Simpson schrieb:
> On Thu, Mar 24, 2011 at 2:51 AM, K, Mythri P <mythripk@ti.com> wrote:
>> Hi Jesse,
>>
>> On Wed, Mar 23, 2011 at 8:48 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
>>> On Wed, 23 Mar 2011 18:58:27 +0530
>>> "K, Mythri P" <mythripk@ti.com> wrote:
>>>
>>>> Hi Dave,
>>>>
>>>> On Wed, Mar 23, 2011 at 6:16 AM, Dave Airlie <airlied@gmail.com> wrote:
>>>>> On Wed, Mar 23, 2011 at 3:32 AM, Mythri P K <mythripk@ti.com> wrote:
>>>>>> Adding support for common EDID parsing in kernel.
>>>>>>
>>>>>> EDID - Extended display identification data is a data structure provided by
>>>>>> a digital display to describe its capabilities to a video source, This a
>>>>>> standard supported by CEA and VESA.
>>>>>>
>>>>>> There are several custom implementations for parsing EDID in kernel, some
>>>>>> of them are present in fbmon.c, drm_edid.c, sh_mobile_hdmi.c, Ideally
>>>>>> parsing of EDID should be done in a library, which is agnostic of the
>>>>>> framework (V4l2, DRM, FB) which is using the functionality, just based on
>>>>>> the raw EDID pointer with size/segment information.
>>>>>>
>>>>>> With other RFC's such as the one below, which tries to standardize HDMI API's
>>>>>> It would be better to have a common EDID code in one place.It also helps to
>>>>>> provide better interoperability with variety of TV/Monitor may be even by
>>>>>> listing out quirks which might get missed with several custom implementation
>>>>>> of EDID.
>>>>>> http://permalink.gmane.org/gmane.linux.drivers.video-input-infrastructure/30401
>>>>>>
>>>>>> This patch tries to add functions to parse some portion EDID (detailed timing,
>>>>>> monitor limits, AV delay information, deep color mode support, Audio and VSDB)
>>>>>> If we can align on this library approach i can enhance this library to parse
>>>>>> other blocks and probably we could also add quirks from other implementation
>>>>>> as well.
>>>>>>
>>>>> If you want to take this approach, you need to start from the DRM EDID parser,
>>>>> its the most well tested and I can guarantee its been plugged into more monitors
>>>>> than any of the others. There is just no way we would move the DRM parser to a
>>>>> library one that isn't derived from it + enhancements, as we'd throw away the
>>>>> years of testing and the regression count would be way too high.
>>>>>
>>>> I had a look at the DRM EDID code, but for quirks it looks pretty much the same.
>>>> yes i could take quirks and other DRM tested code and enhance, but
>>>> still the code has to do away with struct drm_display_mode
>>>> which is very much custom to DRM.
>>> If that's the only issue you have, we could easily rename that
>>> structure or add conversion funcs to a smaller structure if that's what
>>> you need.
>>>
>>> Dave's point is that we can't ditch the existing code without
>>> introducing a lot of risk; it would be better to start a library-ized
>>> EDID codebase from the most complete one we have already, i.e. the DRM
>>> EDID code.
>>>
>> This sounds good. If we can remove the DRM dependent portion to have a
>> library-ized EDID code,
>> That would be perfect. The main Intention to have a library is,
>> Instead of having several different Implementation in kernel, all
>> doing the same EDID parsing , if we could have one single
>> implementation , it would help in better testing and interoperability.
>>
>>> Do you really think the differences between your code and the existing
>>> DRM code are irreconcilable?
>>>
>> On the contrary if there is a library-ized EDID parsing using the
>> drm_edid, and there is any delta / fields( Parsing the video block in
>> CEA extension for Short Video Descriptor, Vendor block for AV delay
>> /Deep color information etc) that are parsed with the RFC i posted i
>> would be happy to add.
>
> Something just occurred to me. Why do video input drivers need EDID?
> Perhaps I'm betraying my youth here, but none of my TV tuners have the
> ability to read EDIDs in from the other side of the coax/RCA jack, and
> IIUC they really only care about whether they're receiving NTSC or
> PAL. The only drivers that should be parsing EDIDs are FB and KMS
> drivers, right?
Traditional TV (PAL/NTSC) supports only a very limited amount of modes and
furthermore within one country it's about 1 or 2 different ones that are
typically needed. It looks like todays TVs support most of those but I've also
seen some terrible cropping or a wrong aspect ratio on TVs. Let's say that had a
relative simple job and they didn't do it always too well, so getting the
information via EDID is better than forcing the user type the info in via a
remote or doing it wrong.
> So why should this be a common library? Most kernel code doesn't need
> it. Or is there a serious need for video input to parse EDIDs?
It's true that most kernel code does not need it as it is only useful for
display output systems (and only the ones that can be connected to something
sending EDID data) but it would be good anyway.
Because sharing code that should fulfill the same purpose is always a good idea.
But of course only if the scope is clearly limited as we don't want to end up
with a mess that nobody dares touching again as it became to complex. So I
totally agree that we should share the common stuff we all need and adding the
extras one needs in the subsystem/driver.
This is good because it looks like we'll have 3 display subsystems within the
kernel for a long future and with a common library the same patch would not need
to be done 3 times but only once. Or even more often if drivers have there
private EDID implementation which I just throw out of mine to replace it later
with a common one.
Regards,
Florian Tobias Schandinat
^ permalink raw reply
* Re: [trivial PATCH 1/2] treewide: Fix iomap resource size
From: Ralf Baechle @ 2011-03-24 22:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <c4422b4a8ee132d3adac95fd86237c61b2f8b364.1300909446.git.joe@perches.com>
On Wed, Mar 23, 2011 at 12:55:36PM -0700, Joe Perches wrote:
Acked-by: Ralf Baechle <ralf@linux-mips.org>
Ralf
^ permalink raw reply
* [PATCH v2] viafb: add VIA slapping capability
From: Florian Tobias Schandinat @ 2011-03-24 21:32 UTC (permalink / raw)
To: linux-fbdev; +Cc: linux-kernel, Florian Tobias Schandinat
In-Reply-To: <4D8B9FBE.6030207@bachelot.org>
This patch introduces dummy functions to execute when we don't know
what we should do (due to missing documentation). They do nothing
but print a nice message in the log explaining the situation.
To trigger this message initial power management support is
activated which might save a bit energy by disabling PLL and clock
if no device is configured to use them.
Note: The message is only shown for the oldest IGPs CLE266 and K400
as for the other platforms there are reasonable assumptions
how it does (hopefully) work.
Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
---
v2: fixed 2 annoying typos
---
drivers/video/via/hw.c | 19 +++++++++++++++++++
drivers/video/via/via_clock.c | 30 ++++++++++++++++++++++++------
2 files changed, 43 insertions(+), 6 deletions(-)
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index f1eff0b..df84251 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -2289,6 +2289,25 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
get_sync(viafbinfo1));
}
+ clock.set_primary_clock_source(VIA_CLKSRC_X1, true);
+ clock.set_secondary_clock_source(VIA_CLKSRC_X1, true);
+
+ if (viaparinfo->shared->iga1_devices) {
+ clock.set_primary_pll_state(VIA_STATE_ON);
+ clock.set_primary_clock_state(VIA_STATE_ON);
+ } else {
+ clock.set_primary_pll_state(VIA_STATE_OFF);
+ clock.set_primary_clock_state(VIA_STATE_OFF);
+ }
+
+ if (viaparinfo->shared->iga2_devices) {
+ clock.set_secondary_pll_state(VIA_STATE_ON);
+ clock.set_secondary_clock_state(VIA_STATE_ON);
+ } else {
+ clock.set_secondary_pll_state(VIA_STATE_OFF);
+ clock.set_secondary_clock_state(VIA_STATE_OFF);
+ }
+
via_set_state(devices, VIA_STATE_ON);
device_screen_on();
return 1;
diff --git a/drivers/video/via/via_clock.c b/drivers/video/via/via_clock.c
index 29afe4c..a829a24 100644
--- a/drivers/video/via/via_clock.c
+++ b/drivers/video/via/via_clock.c
@@ -29,6 +29,9 @@
#include "global.h"
#include "debug.h"
+const char *via_slap = "Please slap VIA Technologies to motivate them "
+ "releasing full documentation for your platform!\n";
+
static inline u32 cle266_encode_pll(struct via_pll_config pll)
{
return (pll.multiplier << 8)
@@ -229,19 +232,34 @@ static void set_secondary_clock_source(enum via_clksrc source, bool use_pll)
via_write_reg_mask(VIACR, 0x6C, data, 0x0F);
}
+static void dummy_set_clock_state(u8 state)
+{
+ printk(KERN_INFO "Using undocumented set clock state.\n%s", via_slap);
+}
+
+static void dummy_set_clock_source(enum via_clksrc source, bool use_pll)
+{
+ printk(KERN_INFO "Using undocumented set clock source.\n%s", via_slap);
+}
+
+static void dummy_set_pll_state(u8 state)
+{
+ printk(KERN_INFO "Using undocumented set PLL state.\n%s", via_slap);
+}
+
void via_clock_init(struct via_clock *clock, int gfx_chip)
{
switch (gfx_chip) {
case UNICHROME_CLE266:
case UNICHROME_K400:
- clock->set_primary_clock_state = NULL;
- clock->set_primary_clock_source = NULL;
- clock->set_primary_pll_state = NULL;
+ clock->set_primary_clock_state = dummy_set_clock_state;
+ clock->set_primary_clock_source = dummy_set_clock_source;
+ clock->set_primary_pll_state = dummy_set_pll_state;
clock->set_primary_pll = cle266_set_primary_pll;
- clock->set_secondary_clock_state = NULL;
- clock->set_secondary_clock_source = NULL;
- clock->set_secondary_pll_state = NULL;
+ clock->set_secondary_clock_state = dummy_set_clock_state;
+ clock->set_secondary_clock_source = dummy_set_clock_source;
+ clock->set_secondary_pll_state = dummy_set_pll_state;
clock->set_secondary_pll = cle266_set_secondary_pll;
break;
case UNICHROME_K800:
--
1.6.3.2
^ permalink raw reply related
* Re: [PATCH 3/3] viafb: add VIA slapping capability
From: Florian Tobias Schandinat @ 2011-03-24 21:11 UTC (permalink / raw)
To: Xavier Bachelot; +Cc: linux-fbdev, linux-kernel
In-Reply-To: <4D8B9FBE.6030207@bachelot.org>
Xavier Bachelot schrieb:
> On 03/24/2011 05:13 PM, Florian Tobias Schandinat wrote:
>> This patch introduces dummy functions to execute when we don't know
>> what we should do (due to missing documentation). They do nothing
>> but print a nice message in the log explaining the situation.
>> To trigger this message initial power management support is
>> activated which might save a bit energy by disabling PLL and clock
>> if no device is configured to use them.
>>
>> Note: The message is only shown for the oldest IGPs CLE266 and K400
>> as for the other platforms there are reasonable assumptions
>> how it does (hopefully) work.
>>
>> Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
>> ---
>
>> +static void dummy_set_clock_source(enum via_clksrc source, bool use_pll)
>> +{
>> + printk(KERN_INFO "Using undocumented set slock soure.\n%s", via_slap);
>
> 2 typos above.
Indeed. Thanks for pointing it out, fixed.
> Regards,
> Xavier
Regards,
Florian Tobias Schandinat
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox