video: tegra: detect fbmem alignment on probe
Jon Mayo [Wed, 23 May 2012 00:24:27 +0000 (17:24 -0700)]
Detect the stride size used by the bootloader.
If DC is not enabled, fallback to a default stride size.

Bug 973111

Change-Id: If04647ddf04a44987cd841062ff30e03fa4d6a02
Signed-off-by: Jon Mayo <jmayo@nvidia.com>
Reviewed-on: http://git-master/r/104031
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>

arch/arm/mach-tegra/include/mach/dc.h
drivers/video/tegra/dc/dc.c
drivers/video/tegra/dc/dc_reg.h
drivers/video/tegra/fb.c

index ab3d4e9..71f1be7 100644 (file)
@@ -503,6 +503,7 @@ struct tegra_dc_platform_data {
 
 #define TEGRA_DC_FLAG_ENABLED          (1 << 0)
 
+int tegra_dc_get_stride(struct tegra_dc *dc, unsigned win);
 struct tegra_dc *tegra_dc_get_dc(unsigned idx);
 struct tegra_dc_win *tegra_dc_get_window(struct tegra_dc *dc, unsigned win);
 bool tegra_dc_get_connected(struct tegra_dc *);
index fb17154..935f18b 100644 (file)
@@ -583,6 +583,23 @@ static unsigned int tegra_dc_has_multiple_dc(void)
        return (cnt > 1);
 }
 
+/* get the stride size of a window.
+ * return: stride size in bytes for window win. or 0 if unavailble. */
+int tegra_dc_get_stride(struct tegra_dc *dc, unsigned win)
+{
+       u32 tmp;
+       u32 stride;
+
+       if (!dc->enabled)
+               return 0;
+       BUG_ON(win > DC_N_WINDOWS);
+       tegra_dc_writel(dc, WINDOW_A_SELECT << win,
+               DC_CMD_DISPLAY_WINDOW_HEADER);
+       tmp = tegra_dc_readl(dc, DC_WIN_LINE_STRIDE);
+       return GET_LINE_STRIDE(tmp);
+}
+EXPORT_SYMBOL(tegra_dc_get_stride);
+
 struct tegra_dc *tegra_dc_get_dc(unsigned idx)
 {
        if (idx < TEGRA_MAX_DC)
index 8b84bff..5eac27a 100644 (file)
 #define DC_WIN_LINE_STRIDE                     0x70a
 #define  LINE_STRIDE(x)                (x)
 #define  UV_LINE_STRIDE(x)     (((x) & 0xffff) << 16)
+#define  GET_LINE_STRIDE(x)    ((x) & 0xffff)
+#define  GET_UV_LINE_STRIDE(x) (((x) >> 16) & 0xffff)
 #define DC_WIN_BUF_STRIDE                      0x70b
 #define DC_WIN_UV_BUF_STRIDE                   0x70c
 #define DC_WIN_BUFFER_ADDR_MODE                        0x70d
index 50aa9b3..1193a2e 100644 (file)
@@ -44,7 +44,7 @@
 #include "dc/dc_priv.h"
 
 /* Pad pitch to 16-byte boundary. */
-#define TEGRA_LINEAR_PITCH_ALIGNMENT 16
+#define TEGRA_LINEAR_PITCH_ALIGNMENT 32
 
 struct tegra_fb_info {
        struct tegra_dc_win     *win;
@@ -527,6 +527,7 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
        unsigned long fb_size = 0;
        unsigned long fb_phys = 0;
        int ret = 0;
+       unsigned stride;
 
        win = tegra_dc_get_window(dc, fb_data->win);
        if (!win) {
@@ -560,6 +561,11 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
                tegra_fb->valid = true;
        }
 
+       stride = tegra_dc_get_stride(dc, 0);
+       if (!stride) /* default to pad the stride to 16-byte boundary. */
+               stride = round_up(info->fix.line_length,
+                       TEGRA_LINEAR_PITCH_ALIGNMENT);
+
        info->fbops = &tegra_fb_ops;
        info->pseudo_palette = pseudo_palette;
        info->screen_base = fb_base;
@@ -574,9 +580,7 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
        info->fix.smem_start    = fb_phys;
        info->fix.smem_len      = fb_size;
        info->fix.line_length = fb_data->xres * fb_data->bits_per_pixel / 8;
-       /* Pad the stride to 16-byte boundary. */
-       info->fix.line_length = round_up(info->fix.line_length,
-                                       TEGRA_LINEAR_PITCH_ALIGNMENT);
+       info->fix.line_length = stride;
 
        info->var.xres                  = fb_data->xres;
        info->var.yres                  = fb_data->yres;