summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/Makefile1
-rw-r--r--arch/arm/mach-tegra/board-ventana-panel.c325
-rw-r--r--arch/arm/mach-tegra/board-ventana-pinmux.c10
-rw-r--r--arch/arm/mach-tegra/board-ventana-power.c4
-rw-r--r--arch/arm/mach-tegra/board-ventana.c4
-rw-r--r--arch/arm/mach-tegra/board-ventana.h1
-rw-r--r--arch/arm/mach-tegra/include/mach/dc.h16
-rw-r--r--arch/arm/mach-tegra/powergate.c1
-rw-r--r--arch/arm/mm/Kconfig9
-rw-r--r--arch/arm/mm/attrib_alloc.c2
-rw-r--r--arch/arm/mm/mmu.c60
-rw-r--r--drivers/spi/spi_tegra.c1
-rw-r--r--drivers/video/tegra/dc/dc.c18
-rw-r--r--drivers/video/tegra/fb.c233
-rw-r--r--drivers/video/tegra/host/debug.c82
-rw-r--r--drivers/video/tegra/host/nvhost_cdma.c21
-rw-r--r--drivers/video/tegra/host/nvhost_cdma.h2
-rw-r--r--drivers/video/tegra/nvmap/nvmap.c15
-rw-r--r--drivers/video/tegra/nvmap/nvmap_dev.c8
-rw-r--r--drivers/video/tegra/nvmap/nvmap_handle.c2
-rw-r--r--drivers/video/tegra/nvmap/nvmap_ioctl.c5
21 files changed, 563 insertions, 257 deletions
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 2d486ad0ffc4..8872cd54337f 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -43,3 +43,4 @@ obj-${CONFIG_MACH_VENTANA} += board-ventana.o
obj-${CONFIG_MACH_VENTANA} += board-ventana-pinmux.o
obj-${CONFIG_MACH_VENTANA} += board-ventana-sdhci.o
obj-${CONFIG_MACH_VENTANA} += board-ventana-power.o
+obj-${CONFIG_MACH_VENTANA} += board-ventana-panel.o
diff --git a/arch/arm/mach-tegra/board-ventana-panel.c b/arch/arm/mach-tegra/board-ventana-panel.c
new file mode 100644
index 000000000000..f3e75e25bf6b
--- /dev/null
+++ b/arch/arm/mach-tegra/board-ventana-panel.c
@@ -0,0 +1,325 @@
+/*
+ * arch/arm/mach-tegra/board-ventana-panel.c
+ *
+ * Copyright (c) 2010, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/resource.h>
+#include <asm/mach-types.h>
+#include <linux/platform_device.h>
+#include <linux/pwm_backlight.h>
+#include <mach/nvhost.h>
+#include <mach/nvmap.h>
+#include <mach/irqs.h>
+#include <mach/iomap.h>
+#include <mach/dc.h>
+#include <mach/fb.h>
+
+#include "devices.h"
+#include "gpio-names.h"
+
+#define ventana_bl_enb TEGRA_GPIO_PD4
+#define ventana_lvds_shutdown TEGRA_GPIO_PB2
+#define ventana_hdmi_hpd TEGRA_GPIO_PN7
+#define ventana_hdmi_enb TEGRA_GPIO_PV5
+
+static int ventana_backlight_init(struct device *dev) {
+ int ret;
+
+ ret = gpio_request(ventana_bl_enb, "backlight_enb");
+ if (ret < 0)
+ return ret;
+
+ ret = gpio_direction_output(ventana_bl_enb, 1);
+ if (ret < 0)
+ gpio_free(ventana_bl_enb);
+ else
+ tegra_gpio_enable(ventana_bl_enb);
+
+ return ret;
+};
+
+static void ventana_backlight_exit(struct device *dev) {
+ gpio_set_value(ventana_bl_enb, 0);
+ gpio_free(ventana_bl_enb);
+ tegra_gpio_disable(ventana_bl_enb);
+}
+
+static int ventana_backlight_notify(struct device *unused, int brightness)
+{
+ gpio_set_value(ventana_bl_enb, !!brightness);
+ return brightness;
+}
+
+static struct platform_pwm_backlight_data ventana_backlight_data = {
+ .pwm_id = 2,
+ .max_brightness = 255,
+ .dft_brightness = 224,
+ .pwm_period_ns = 5000000,
+ .init = ventana_backlight_init,
+ .exit = ventana_backlight_exit,
+ .notify = ventana_backlight_notify,
+};
+
+static struct platform_device ventana_backlight_device = {
+ .name = "pwm-backlight",
+ .id = -1,
+ .dev = {
+ .platform_data = &ventana_backlight_data,
+ },
+};
+
+static int ventana_panel_enable(void)
+{
+ static struct regulator *reg = NULL;
+
+ if (reg == NULL) {
+ reg = regulator_get(NULL, "avdd_lvds");
+ if (WARN_ON(IS_ERR(reg)))
+ pr_err("%s: couldn't get regulator avdd_lvds: %ld\n",
+ __func__, PTR_ERR(reg));
+ else
+ regulator_enable(reg);
+ }
+
+ gpio_set_value(ventana_lvds_shutdown, 1);
+ return 0;
+}
+
+static int ventana_panel_disable(void)
+{
+ gpio_set_value(ventana_lvds_shutdown, 0);
+ return 0;
+}
+
+static int ventana_hdmi_enable(void)
+{
+ gpio_set_value(ventana_hdmi_enb, 1);
+ return 0;
+}
+
+static int ventana_hdmi_disable(void)
+{
+ gpio_set_value(ventana_hdmi_enb, 0);
+ return 0;
+}
+
+static struct resource ventana_disp1_resources[] = {
+ {
+ .name = "irq",
+ .start = INT_DISPLAY_GENERAL,
+ .end = INT_DISPLAY_GENERAL,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "regs",
+ .start = TEGRA_DISPLAY_BASE,
+ .end = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE-1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "fbmem",
+ .start = 0x18012000,
+ .end = 0x18414000 - 1, /* enough for 1080P 16bpp */
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct resource ventana_disp2_resources[] = {
+ {
+ .name = "irq",
+ .start = INT_DISPLAY_B_GENERAL,
+ .end = INT_DISPLAY_B_GENERAL,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "regs",
+ .start = TEGRA_DISPLAY2_BASE,
+ .end = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "fbmem",
+ .flags = IORESOURCE_MEM,
+ .start = 0x18414000,
+ .end = 0x18BFD000 - 1,
+ },
+ {
+ .name = "hdmi_regs",
+ .start = TEGRA_HDMI_BASE,
+ .end = TEGRA_HDMI_BASE + TEGRA_HDMI_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct tegra_dc_mode ventana_panel_modes[] = {
+ {
+ .pclk = 62200000,
+ .h_ref_to_sync = 11,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 58,
+ .v_sync_width = 4,
+ .h_back_porch = 58,
+ .v_back_porch = 4,
+ .h_active = 1366,
+ .v_active = 768,
+ .h_front_porch = 58,
+ .v_front_porch = 4,
+ },
+};
+
+static struct tegra_fb_data ventana_fb_data = {
+ .win = 0,
+ .xres = 1366,
+ .yres = 768,
+ .bits_per_pixel = 16,
+};
+
+static struct tegra_fb_data ventana_hdmi_fb_data = {
+ .win = 0,
+ .xres = 1280,
+ .yres = 720,
+ .bits_per_pixel = 16,
+};
+
+static struct tegra_dc_out ventana_disp1_out = {
+ .type = TEGRA_DC_OUT_RGB,
+
+ .align = TEGRA_DC_ALIGN_MSB,
+ .order = TEGRA_DC_ORDER_RED_BLUE,
+
+ .modes = ventana_panel_modes,
+ .n_modes = ARRAY_SIZE(ventana_panel_modes),
+
+ .enable = ventana_panel_enable,
+ .disable = ventana_panel_disable,
+};
+
+static struct tegra_dc_out ventana_disp2_out = {
+ .type = TEGRA_DC_OUT_HDMI,
+ .flags = TEGRA_DC_OUT_HOTPLUG_HIGH,
+
+ .dcc_bus = 1,
+ .hotplug_gpio = ventana_hdmi_hpd,
+
+ .align = TEGRA_DC_ALIGN_MSB,
+ .order = TEGRA_DC_ORDER_RED_BLUE,
+
+ .enable = ventana_hdmi_enable,
+ .disable = ventana_hdmi_disable,
+};
+
+static struct tegra_dc_platform_data ventana_disp1_pdata = {
+ .flags = TEGRA_DC_FLAG_ENABLED,
+ .default_out = &ventana_disp1_out,
+ .fb = &ventana_fb_data,
+};
+
+static struct tegra_dc_platform_data ventana_disp2_pdata = {
+ .flags = TEGRA_DC_FLAG_ENABLED,
+ .default_out = &ventana_disp2_out,
+ .fb = &ventana_hdmi_fb_data,
+};
+
+static struct nvhost_device ventana_disp1_device = {
+ .name = "tegradc",
+ .id = 0,
+ .resource = ventana_disp1_resources,
+ .num_resources = ARRAY_SIZE(ventana_disp1_resources),
+ .dev = {
+ .platform_data = &ventana_disp1_pdata,
+ },
+};
+
+static struct nvhost_device ventana_disp2_device = {
+ .name = "tegradc",
+ .id = 1,
+ .resource = ventana_disp2_resources,
+ .num_resources = ARRAY_SIZE(ventana_disp2_resources),
+ .dev = {
+ .platform_data = &ventana_disp2_pdata,
+ },
+};
+
+static struct nvmap_platform_carveout ventana_carveouts[] = {
+ [0] = {
+ .name = "iram",
+ .usage_mask = NVMAP_HEAP_CARVEOUT_IRAM,
+ .base = TEGRA_IRAM_BASE,
+ .size = TEGRA_IRAM_SIZE,
+ .buddy_size = 0, /* no buddy allocation for IRAM */
+ },
+ [1] = {
+ .name = "generic-0",
+ .usage_mask = NVMAP_HEAP_CARVEOUT_GENERIC,
+ .base = 0x18C00000,
+ .size = SZ_128M - 0xC00000,
+ .buddy_size = SZ_32K,
+ },
+};
+
+static struct nvmap_platform_data ventana_nvmap_data = {
+ .carveouts = ventana_carveouts,
+ .nr_carveouts = ARRAY_SIZE(ventana_carveouts),
+};
+
+static struct platform_device ventana_nvmap_device = {
+ .name = "tegra-nvmap",
+ .id = -1,
+ .dev = {
+ .platform_data = &ventana_nvmap_data,
+ },
+};
+
+static struct platform_device *ventana_gfx_devices[] __initdata = {
+ &ventana_nvmap_device,
+ &tegra_grhost_device,
+ &tegra_pwfm2_device,
+ &ventana_backlight_device,
+};
+
+int __init ventana_panel_init(void)
+{
+ int err;
+
+ gpio_request(ventana_lvds_shutdown, "lvds_shdn");
+ gpio_direction_output(ventana_lvds_shutdown, 1);
+ tegra_gpio_enable(ventana_lvds_shutdown);
+
+ gpio_request(ventana_hdmi_enb, "hdmi_5v_en");
+ gpio_direction_output(ventana_hdmi_enb, 0);
+ tegra_gpio_enable(ventana_hdmi_enb);
+
+ gpio_request(ventana_hdmi_hpd, "hdmi_hpd");
+ gpio_direction_input(ventana_hdmi_hpd);
+ tegra_gpio_enable(ventana_hdmi_hpd);
+
+ err = platform_add_devices(ventana_gfx_devices,
+ ARRAY_SIZE(ventana_gfx_devices));
+
+ if (!err)
+ err = nvhost_device_register(&ventana_disp1_device);
+
+ if (!err)
+ err = nvhost_device_register(&ventana_disp2_device);
+
+ return err;
+}
+
diff --git a/arch/arm/mach-tegra/board-ventana-pinmux.c b/arch/arm/mach-tegra/board-ventana-pinmux.c
index c9194db3684a..e85034ccda50 100644
--- a/arch/arm/mach-tegra/board-ventana-pinmux.c
+++ b/arch/arm/mach-tegra/board-ventana-pinmux.c
@@ -65,7 +65,7 @@ static __initdata struct tegra_pingroup_config ventana_pinmux[] = {
{TEGRA_PINGROUP_GMC, TEGRA_MUX_UARTD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_GMD, TEGRA_MUX_SFLASH, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_GME, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_GPU, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
+ {TEGRA_PINGROUP_GPU, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_GPU7, TEGRA_MUX_RTCK, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_GPV, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
@@ -103,12 +103,12 @@ static __initdata struct tegra_pingroup_config ventana_pinmux[] = {
{TEGRA_PINGROUP_LHP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_LHP2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_LHS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LM0, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
+ {TEGRA_PINGROUP_LM0, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_LM1, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_LPP, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_LPW0, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
+ {TEGRA_PINGROUP_LPW0, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_LPW1, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LPW2, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
+ {TEGRA_PINGROUP_LPW2, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_LSC0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_LSC1, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_LSCK, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
@@ -128,7 +128,7 @@ static __initdata struct tegra_pingroup_config ventana_pinmux[] = {
{TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_SLXA, TEGRA_MUX_PCIE, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_SLXC, TEGRA_MUX_SPDIF, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_SLXD, TEGRA_MUX_SPDIF, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
+ {TEGRA_PINGROUP_SLXD, TEGRA_MUX_SPDIF, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_SLXK, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_SPDI, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_SPDO, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
diff --git a/arch/arm/mach-tegra/board-ventana-power.c b/arch/arm/mach-tegra/board-ventana-power.c
index c76710c8bdce..e2c6f3349206 100644
--- a/arch/arm/mach-tegra/board-ventana-power.c
+++ b/arch/arm/mach-tegra/board-ventana-power.c
@@ -86,8 +86,7 @@ static void set_charge(int flags)
gpio_set_value(charge_disable, 0);
else if (!flags)
gpio_set_value(charge_disable, 1);
- else
- BUG();
+ /* USB charging not supported on Ventana */
}
static struct resource ventana_pda_resources[] = {
@@ -139,6 +138,7 @@ static struct regulator_consumer_supply tps658621_ldo2_supply[] = {
static struct regulator_consumer_supply tps658621_ldo3_supply[] = {
REGULATOR_SUPPLY("avdd_usb", NULL),
REGULATOR_SUPPLY("avdd_usb_pll", NULL),
+ REGULATOR_SUPPLY("avdd_lvds", NULL),
};
static struct regulator_consumer_supply tps658621_ldo4_supply[] = {
REGULATOR_SUPPLY("avdd_osc", NULL),
diff --git a/arch/arm/mach-tegra/board-ventana.c b/arch/arm/mach-tegra/board-ventana.c
index a1d55e71a820..60948ad9dba4 100644
--- a/arch/arm/mach-tegra/board-ventana.c
+++ b/arch/arm/mach-tegra/board-ventana.c
@@ -35,6 +35,7 @@
#include <linux/input.h>
#include <linux/usb/android_composite.h>
+#include <mach/clk.h>
#include <mach/iomap.h>
#include <mach/irqs.h>
#include <mach/pinmux.h>
@@ -77,7 +78,7 @@ static __initdata struct tegra_clk_init_table ventana_clk_init_table[] = {
/* name parent rate enabled */
{ "uartd", "pll_p", 216000000, true},
{ "pll_m", "clk_m", 600000000, true},
- { "emc", "pll_m", 600000000, true},
+ { "pwm", "clk_32k", 32768, false},
{ NULL, NULL, 0, 0},
};
@@ -258,6 +259,7 @@ static void __init tegra_ventana_init(void)
ventana_regulator_init();
ventana_touch_init();
ventana_keys_init();
+ ventana_panel_init();
}
MACHINE_START(VENTANA, "ventana")
diff --git a/arch/arm/mach-tegra/board-ventana.h b/arch/arm/mach-tegra/board-ventana.h
index 2b19f64256f8..39703583249d 100644
--- a/arch/arm/mach-tegra/board-ventana.h
+++ b/arch/arm/mach-tegra/board-ventana.h
@@ -20,5 +20,6 @@
int ventana_regulator_init(void);
int ventana_sdhci_init(void);
int ventana_pinmux_init(void);
+int ventana_panel_init(void);
#endif
diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h
index 49c09a177d00..f33c724ed864 100644
--- a/arch/arm/mach-tegra/include/mach/dc.h
+++ b/arch/arm/mach-tegra/include/mach/dc.h
@@ -25,15 +25,6 @@
#define TEGRA_MAX_DC 2
#define DC_N_WINDOWS 3
-#define TEGRA_DC_PITCH_ATOM 16
-#define TEGRA_DC_TILED_ATOM 16
-
-enum tegra_win_layout {
- TEGRA_WIN_LAYOUT_PITCH,
- TEGRA_WIN_LAYOUT_TILED,
- TEGRA_WIN_LAYOUT_LINEAR_TILED,
-};
-
struct tegra_dc_mode {
int pclk;
int h_ref_to_sync;
@@ -105,14 +96,14 @@ struct tegra_dc_win {
unsigned out_w;
unsigned out_h;
unsigned z;
- enum tegra_win_layout layout;
int dirty;
struct tegra_dc *dc;
- struct nvmap_handle_ref *surface;
+ struct nvmap_handle_ref *cur_handle;
};
+
#define TEGRA_WIN_FLAG_ENABLED (1 << 0)
#define TEGRA_WIN_FLAG_BLEND_PREMULT (1 << 1)
#define TEGRA_WIN_FLAG_BLEND_COVERAGE (1 << 2)
@@ -180,7 +171,4 @@ int tegra_dc_sync_windows(struct tegra_dc_win *windows[], int n);
int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode);
-ssize_t tegra_dc_compute_stride(int xres, int bpp,
- enum tegra_win_layout layout);
-
#endif
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
index 9fbe72716636..583a7e3751ac 100644
--- a/arch/arm/mach-tegra/powergate.c
+++ b/arch/arm/mach-tegra/powergate.c
@@ -144,6 +144,7 @@ int tegra_powergate_sequence_power_up(int id, struct clk *clk)
if (ret)
goto err_clamp;
+ udelay(10);
tegra_periph_reset_deassert(clk);
return 0;
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index d7fd03bd80eb..da057fcd0491 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -857,12 +857,3 @@ config ARCH_HAS_BARRIERS
help
This option allows the use of custom mandatory barriers
included via the mach/barriers.h file.
-
-config ARCH_LOWMEM_IN_PTES
- bool
- help
- This option will map the kernel direct-mapped lowmem region
- using page table mappings rather than section mappings.
-
-config ARCH_USES_PG_UNCACHED
- bool
diff --git a/arch/arm/mm/attrib_alloc.c b/arch/arm/mm/attrib_alloc.c
index 0966a8b8bf41..73be2d664669 100644
--- a/arch/arm/mm/attrib_alloc.c
+++ b/arch/arm/mm/attrib_alloc.c
@@ -121,6 +121,6 @@ struct page *arm_attrib_alloc_pages_exact_node(int nid, gfp_t gfp,
update_pte(p, prot);
}
base = page_to_phys(page);
- outer_flush_range(base, base + (size >> PAGE_SHIFT));
+ outer_flush_range(base, base + size);
return page;
}
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 6e65f186905c..6a3a2d0cd6db 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -251,7 +251,6 @@ static struct mem_type mem_types[] = {
L_PTE_USER | L_PTE_EXEC,
.prot_l1 = PMD_TYPE_TABLE,
.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
- .prot_l1 = PMD_TYPE_TABLE,
.domain = DOMAIN_KERNEL,
},
[MT_ROM] = {
@@ -556,30 +555,6 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
} while (pte++, addr += PAGE_SIZE, addr != end);
}
-#ifdef CONFIG_ARCH_LOWMEM_IN_PTES
-static void __init realloc_init_pte(pmd_t *pmd, unsigned long addr,
- unsigned long end, unsigned long pfn,
- const struct mem_type *type)
-{
- pte_t *pte, *ptep;
-
- if ((pmd_val(*pmd) & PMD_TYPE_MASK) != PMD_TYPE_SECT)
- return;
-
- pte = early_alloc(2 * PTRS_PER_PTE * sizeof(pte_t));
- if (WARN_ON(!pte))
- return;
-
- ptep = pte + PTRS_PER_PTE + __pte_index(addr);
- do {
- set_pte_ext(ptep, pfn_pte(pfn, __pgprot(type->prot_pte)), 0);
- pfn++;
- } while (ptep++, addr += PAGE_SIZE, addr != end);
-
- __pmd_populate(pmd, __pa(pte) | type->prot_l1);
-}
-#endif
-
static void __init alloc_init_section(pgd_t *pgd, unsigned long addr,
unsigned long end, unsigned long phys,
const struct mem_type *type)
@@ -1042,40 +1017,6 @@ static void __init map_lowmem(void)
}
}
-static void __init remap_lowmem(void)
-{
-#ifdef CONFIG_ARCH_LOWMEM_IN_PTES
- struct meminfo *mi = &meminfo;
- const struct mem_type *type = &mem_types[MT_MEMORY];
- int i;
-
- for (i = 0; i < mi->nr_banks; i++) {
- pgd_t *pgd;
- unsigned long phys, addr, end;
- struct membank *bank = &mi->bank[i];
-
- if (bank->highmem)
- continue;
-
- phys = __pfn_to_phys(bank_pfn_start(bank));
- addr = __phys_to_virt(bank_phys_start(bank));
- end = addr + bank_phys_size(bank);
-
- pgd = pgd_offset_k(addr);
- do {
- unsigned long next = pgd_addr_end(addr, end);
- pmd_t *pmd = pmd_offset(pgd, addr);
-
- realloc_init_pte(pmd, addr, next,
- __phys_to_pfn(phys), type);
-
- phys += next - addr;
- addr = next;
- } while (pgd++, addr != end);
- }
-#endif
-}
-
static int __init meminfo_cmp(const void *_a, const void *_b)
{
const struct membank *a = _a, *b = _b;
@@ -1097,7 +1038,6 @@ void __init paging_init(struct machine_desc *mdesc)
sanity_check_meminfo();
prepare_page_table();
map_lowmem();
- remap_lowmem();
devicemaps_init(mdesc);
kmap_init();
diff --git a/drivers/spi/spi_tegra.c b/drivers/spi/spi_tegra.c
index 6023da9a103a..3709d5dccd76 100644
--- a/drivers/spi/spi_tegra.c
+++ b/drivers/spi/spi_tegra.c
@@ -274,6 +274,7 @@ static void spi_tegra_start_transfer(struct spi_device *spi,
val |= SLINK_TXEN;
val |= SLINK_SS_EN_CS(spi->chip_select);
val |= SLINK_SPIE;
+ val |= SLINK_SS_SETUP(3);
spi_tegra_writel(tspi, val, SLINK_COMMAND2);
val = spi_tegra_readl(tspi, SLINK_COMMAND);
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index 16e6a454336d..65a36ddd2514 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -328,20 +328,6 @@ struct tegra_dc *tegra_dc_get_dc(unsigned idx)
}
EXPORT_SYMBOL(tegra_dc_get_dc);
-ssize_t tegra_dc_compute_stride(int xres, int bpp, enum tegra_win_layout layout)
-{
- unsigned int raw_stride = (xres * bpp) / 8;
- unsigned int k, n = 0;
-
- if (layout == TEGRA_WIN_LAYOUT_PITCH)
- return ALIGN(raw_stride, TEGRA_DC_PITCH_ATOM);
- else if (layout == TEGRA_WIN_LAYOUT_TILED)
- return ALIGN(raw_stride, TEGRA_DC_TILED_ATOM);
- else
- return -EINVAL;
-}
-EXPORT_SYMBOL(tegra_dc_compute_stride);
-
struct tegra_dc_win *tegra_dc_get_window(struct tegra_dc *dc, unsigned win)
{
if (win >= dc->n_windows)
@@ -1066,8 +1052,10 @@ static int tegra_dc_suspend(struct nvhost_device *ndev, pm_message_t state)
dev_info(&ndev->dev, "suspend\n");
+ mutex_lock(&dc->lock);
if (dc->enabled)
_tegra_dc_disable(dc);
+ mutex_unlock(&dc->lock);
return 0;
}
@@ -1078,8 +1066,10 @@ static int tegra_dc_resume(struct nvhost_device *ndev)
dev_info(&ndev->dev, "resume\n");
+ mutex_lock(&dc->lock);
if (dc->enabled)
_tegra_dc_enable(dc);
+ mutex_unlock(&dc->lock);
return 0;
}
diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c
index 1656a6e49279..87ba58b06cd1 100644
--- a/drivers/video/tegra/fb.c
+++ b/drivers/video/tegra/fb.c
@@ -59,17 +59,16 @@ struct tegra_fb_info {
};
struct tegra_fb_flip_win {
- struct tegra_dc_win win_data;
- struct tegra_dc_win *dc_win;
- s32 pre_syncpt_id;
- u32 pre_syncpt_val;
+ struct tegra_fb_windowattr attr;
+ struct nvmap_handle_ref *handle;
+ dma_addr_t phys_addr;
};
struct tegra_fb_flip_data {
- struct work_struct work;
- struct tegra_fb_info *fb;
- struct tegra_fb_flip_win windows[TEGRA_FB_FLIP_N_WINDOWS];
- u32 syncpt_max;
+ struct work_struct work;
+ struct tegra_fb_info *fb;
+ struct tegra_fb_flip_win win[TEGRA_FB_FLIP_N_WINDOWS];
+ u32 syncpt_max;
};
/* palette array used by the fbcon */
@@ -149,10 +148,7 @@ static int tegra_fb_set_par(struct fb_info *info)
default:
return -EINVAL;
}
-
- info->fix.line_length = tegra_dc_compute_stride(var->xres,
- var->bits_per_pixel, TEGRA_WIN_LAYOUT_PITCH);
- tegra_fb->win->stride = info->fix.line_length;
+ info->fix.line_length = var->xres * var->bits_per_pixel / 8;
if (var->pixclock) {
struct tegra_dc_mode mode;
@@ -251,10 +247,10 @@ static int tegra_fb_pan_display(struct fb_var_screeninfo *var,
tegra_dc_update_windows(&tegra_fb->win, 1);
tegra_dc_sync_windows(&tegra_fb->win, 1);
- if (WARN_ON(tegra_fb->win->surface)) {
- nvmap_unpin(tegra_fb->fb_nvmap, tegra_fb->win->surface);
- nvmap_free(tegra_fb->fb_nvmap, tegra_fb->win->surface);
- tegra_fb->win->surface = NULL;
+ if (WARN_ON(tegra_fb->win->cur_handle)) {
+ nvmap_unpin(tegra_fb->fb_nvmap, tegra_fb->win->cur_handle);
+ nvmap_free(tegra_fb->fb_nvmap, tegra_fb->win->cur_handle);
+ tegra_fb->win->cur_handle = NULL;
}
return 0;
@@ -299,131 +295,140 @@ static int tegra_fb_set_nvmap_fd(struct tegra_fb_info *tegra_fb, int fd)
return 0;
}
-static int tegra_fb_set_windowattr(struct tegra_fb_info *tegra_fb,
- struct tegra_dc_win *win,
- const struct tegra_fb_windowattr *attr)
+static int tegra_fb_pin_window(struct tegra_fb_info *tegra_fb,
+ struct tegra_fb_flip_win *flip_win)
{
- struct nvmap_handle_ref *r_dupe;
- struct nvmap_handle *h_win;
+ struct nvmap_handle_ref *win_dupe;
+ struct nvmap_handle *win_handle;
+ unsigned long buff_id = flip_win->attr.buff_id;
- if (!attr->buff_id) {
- win->flags = 0;
- win->surface = NULL;
+ if (!buff_id)
return 0;
- }
- h_win = nvmap_get_handle_id(tegra_fb->user_nvmap, attr->buff_id);
- if (h_win == NULL) {
+ win_handle = nvmap_get_handle_id(tegra_fb->user_nvmap, buff_id);
+ if (win_handle == NULL) {
dev_err(&tegra_fb->ndev->dev, "%s: flip invalid "
- "handle %08x\n", current->comm, attr->buff_id);
+ "handle %08lx\n", current->comm, buff_id);
return -EPERM;
}
/* duplicate the new framebuffer's handle into the fb driver's
* nvmap context, to ensure that the handle won't be freed as
* long as it is in-use by the fb driver */
- r_dupe = nvmap_duplicate_handle_id(tegra_fb->fb_nvmap, attr->buff_id);
- nvmap_handle_put(h_win);
+ win_dupe = nvmap_duplicate_handle_id(tegra_fb->fb_nvmap, buff_id);
+ nvmap_handle_put(win_handle);
- if (IS_ERR(r_dupe)) {
+ if (IS_ERR(win_dupe)) {
dev_err(&tegra_fb->ndev->dev, "couldn't duplicate handle\n");
- return PTR_ERR(r_dupe);
+ return PTR_ERR(win_dupe);
+ }
+
+ flip_win->handle = win_dupe;
+
+ flip_win->phys_addr = nvmap_pin(tegra_fb->fb_nvmap, win_dupe);
+ if (IS_ERR((void *)flip_win->phys_addr)) {
+ dev_err(&tegra_fb->ndev->dev, "couldn't pin handle\n");
+ nvmap_free(tegra_fb->fb_nvmap, win_dupe);
+ return PTR_ERR((void *)flip_win->phys_addr);
}
- win->surface = r_dupe;
+ return 0;
+}
+
+static int tegra_fb_set_windowattr(struct tegra_fb_info *tegra_fb,
+ struct tegra_dc_win *win,
+ const struct tegra_fb_flip_win *flip_win)
+{
+ if (flip_win->handle == NULL) {
+ win->flags = 0;
+ return 0;
+ }
win->flags = TEGRA_WIN_FLAG_ENABLED;
- if (attr->blend == TEGRA_FB_WIN_BLEND_PREMULT)
+ if (flip_win->attr.blend == TEGRA_FB_WIN_BLEND_PREMULT)
win->flags |= TEGRA_WIN_FLAG_BLEND_PREMULT;
- else if (attr->blend == TEGRA_FB_WIN_BLEND_COVERAGE)
+ else if (flip_win->attr.blend == TEGRA_FB_WIN_BLEND_COVERAGE)
win->flags |= TEGRA_WIN_FLAG_BLEND_COVERAGE;
- win->fmt = attr->pixformat;
- win->x = attr->x;
- win->y = attr->y;
- win->w = attr->w;
- win->h = attr->h;
- win->out_x = attr->out_x;
- win->out_y = attr->out_y;
- win->out_w = attr->out_w;
- win->out_h = attr->out_h;
- win->z = attr->z;
-
- win->phys_addr = nvmap_pin(tegra_fb->fb_nvmap, r_dupe);
- if (IS_ERR((void *)win->phys_addr)) {
- dev_err(&tegra_fb->ndev->dev, "couldn't pin handle\n");
- nvmap_free(tegra_fb->fb_nvmap, r_dupe);
- return (int)win->phys_addr;
- }
+ win->fmt = flip_win->attr.pixformat;
+ win->x = flip_win->attr.x;
+ win->y = flip_win->attr.y;
+ win->w = flip_win->attr.w;
+ win->h = flip_win->attr.h;
+ win->out_x = flip_win->attr.out_x;
+ win->out_y = flip_win->attr.out_y;
+ win->out_w = flip_win->attr.out_w;
+ win->out_h = flip_win->attr.out_h;
+ win->z = flip_win->attr.z;
+ win->cur_handle = flip_win->handle;
+
/* STOPSHIP verify that this won't read outside of the surface */
- win->phys_addr += attr->offset;
- win->stride = attr->stride;
+ win->phys_addr = flip_win->phys_addr + flip_win->attr.offset;
+ win->stride = flip_win->attr.stride;
+
+ if ((s32)flip_win->attr.pre_syncpt_id >= 0) {
+ nvhost_syncpt_wait_timeout(&tegra_fb->ndev->host->syncpt,
+ flip_win->attr.pre_syncpt_id,
+ flip_win->attr.pre_syncpt_val,
+ msecs_to_jiffies(500));
+ }
+
return 0;
}
-static void tegra_fb_flip_work(struct work_struct *work)
+static void tegra_fb_flip_worker(struct work_struct *work)
{
- struct tegra_fb_flip_data *data;
+ struct tegra_fb_flip_data *data =
+ container_of(work, struct tegra_fb_flip_data, work);
+ struct tegra_fb_info *tegra_fb = data->fb;
+ struct tegra_dc_win *win;
struct tegra_dc_win *wins[TEGRA_FB_FLIP_N_WINDOWS];
- struct nvmap_handle_ref *surfs[TEGRA_FB_FLIP_N_WINDOWS];
+ struct nvmap_handle_ref *unpin_handles[TEGRA_FB_FLIP_N_WINDOWS];
int i, nr_win = 0, nr_unpin = 0;
data = container_of(work, struct tegra_fb_flip_data, work);
for (i = 0; i < TEGRA_FB_FLIP_N_WINDOWS; i++) {
- struct tegra_fb_flip_win *flip_win = &data->windows[i];
+ struct tegra_fb_flip_win *flip_win = &data->win[i];
+ int idx = flip_win->attr.index;
+ win = tegra_dc_get_window(tegra_fb->win->dc, idx);
- if (!flip_win->dc_win)
+ if (!win)
continue;
- if (flip_win->dc_win->flags && flip_win->dc_win->surface)
- surfs[nr_unpin++] = flip_win->dc_win->surface;
+ if (win->flags && win->cur_handle)
+ unpin_handles[nr_unpin++] = win->cur_handle;
- wins[nr_win++] = flip_win->dc_win;
+ tegra_fb_set_windowattr(tegra_fb, win, &data->win[i]);
- flip_win->dc_win->flags = flip_win->win_data.flags;
- if (!flip_win->dc_win->flags)
- continue;
+ wins[nr_win++] = win;
- flip_win->dc_win->surface = flip_win->win_data.surface;
- flip_win->dc_win->fmt = flip_win->win_data.fmt;
- flip_win->dc_win->x = flip_win->win_data.x;
- flip_win->dc_win->y = flip_win->win_data.y;
- flip_win->dc_win->w = flip_win->win_data.w;
- flip_win->dc_win->h = flip_win->win_data.h;
- flip_win->dc_win->out_x = flip_win->win_data.out_x;
- flip_win->dc_win->out_y = flip_win->win_data.out_y;
- flip_win->dc_win->out_w = flip_win->win_data.out_w;
- flip_win->dc_win->out_h = flip_win->win_data.out_h;
- flip_win->dc_win->z = flip_win->win_data.z;
- flip_win->dc_win->phys_addr = flip_win->win_data.phys_addr;
- flip_win->dc_win->stride = flip_win->win_data.stride;
-
- if (flip_win->pre_syncpt_id < 0)
+#if 0
+ if (flip_win->attr.pre_syncpt_id < 0)
continue;
+ printk("%08x %08x\n",
+ flip_win->attr.pre_syncpt_id,
+ flip_win->attr.pre_syncpt_val);
- nvhost_syncpt_wait_timeout(&data->fb->ndev->host->syncpt,
- flip_win->pre_syncpt_id,
- flip_win->pre_syncpt_val,
+ nvhost_syncpt_wait_timeout(&tegra_fb->ndev->host->syncpt,
+ flip_win->attr.pre_syncpt_id,
+ flip_win->attr.pre_syncpt_val,
msecs_to_jiffies(500));
+#endif
}
- if (!nr_win)
- goto free_data;
-
tegra_dc_update_windows(wins, nr_win);
/* TODO: implement swapinterval here */
tegra_dc_sync_windows(wins, nr_win);
- tegra_dc_incr_syncpt_min(data->fb->win->dc, data->syncpt_max);
+ tegra_dc_incr_syncpt_min(tegra_fb->win->dc, data->syncpt_max);
/* unpin and deref previous front buffers */
for (i = 0; i < nr_unpin; i++) {
- nvmap_unpin(data->fb->fb_nvmap, surfs[i]);
- nvmap_free(data->fb->fb_nvmap, surfs[i]);
+ nvmap_unpin(tegra_fb->fb_nvmap, unpin_handles[i]);
+ nvmap_free(tegra_fb->fb_nvmap, unpin_handles[i]);
}
-free_data:
kfree(data);
}
@@ -432,7 +437,6 @@ static int tegra_fb_flip(struct tegra_fb_info *tegra_fb,
{
struct tegra_fb_flip_data *data;
struct tegra_fb_flip_win *flip_win;
- struct tegra_dc *dc = tegra_fb->win->dc;
u32 syncpt_max;
int i, err;
@@ -442,51 +446,46 @@ static int tegra_fb_flip(struct tegra_fb_info *tegra_fb,
if (WARN_ON(!tegra_fb->ndev))
return -EFAULT;
- data = kmalloc(sizeof(*data), GFP_KERNEL);
- if (!data) {
- dev_err(&tegra_fb->ndev->dev, "no memory for flip\n");
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL) {
+ dev_err(&tegra_fb->ndev->dev,
+ "can't allocate memory for flip\n");
return -ENOMEM;
}
- INIT_WORK(&data->work, tegra_fb_flip_work);
+ INIT_WORK(&data->work, tegra_fb_flip_worker);
data->fb = tegra_fb;
for (i = 0; i < TEGRA_FB_FLIP_N_WINDOWS; i++) {
+ flip_win = &data->win[i];
- flip_win = &data->windows[i];
- flip_win->dc_win = tegra_dc_get_window(dc, args->win[i].index);
- flip_win->pre_syncpt_id = args->win[i].pre_syncpt_id;
- flip_win->pre_syncpt_val = args->win[i].pre_syncpt_val;
-
- if (!flip_win->dc_win)
- continue;
+ memcpy(&flip_win->attr, &args->win[i], sizeof(flip_win->attr));
- err = tegra_fb_set_windowattr(tegra_fb, &flip_win->win_data,
- &args->win[i]);
- if (err) {
- dev_err(&tegra_fb->ndev->dev, "error setting window "
- "attributes\n");
+ err = tegra_fb_pin_window(tegra_fb, flip_win);
+ if (err < 0) {
+ dev_err(&tegra_fb->ndev->dev,
+ "error setting window attributes\n");
goto surf_err;
}
}
- syncpt_max = tegra_dc_incr_syncpt_max(dc);
+ syncpt_max = tegra_dc_incr_syncpt_max(tegra_fb->win->dc);
data->syncpt_max = syncpt_max;
queue_work(tegra_fb->flip_wq, &data->work);
args->post_syncpt_val = syncpt_max;
- args->post_syncpt_id = tegra_dc_get_syncpt_id(dc);
+ args->post_syncpt_id = tegra_dc_get_syncpt_id(tegra_fb->win->dc);
return 0;
surf_err:
while (i--) {
- if (data->windows[i].win_data.surface) {
+ if (data->win[i].handle) {
nvmap_unpin(tegra_fb->fb_nvmap,
- data->windows[i].win_data.surface);
+ data->win[i].handle);
nvmap_free(tegra_fb->fb_nvmap,
- data->windows[i].win_data.surface);
+ data->win[i].handle);
}
}
kfree(data);
@@ -679,9 +678,7 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
win->z = 0;
win->phys_addr = fb_phys;
win->virt_addr = fb_base;
- win->layout = TEGRA_WIN_LAYOUT_PITCH;
- win->stride = tegra_dc_compute_stride(fb_data->xres,
- fb_data->bits_per_pixel, win->layout);
+ win->stride = fb_data->xres * fb_data->bits_per_pixel / 8;
win->flags = TEGRA_WIN_FLAG_ENABLED;
if (fb_mem)
@@ -715,9 +712,9 @@ void tegra_fb_unregister(struct tegra_fb_info *fb_info)
{
struct fb_info *info = fb_info->info;
- if (fb_info->win->surface) {
- nvmap_unpin(fb_info->fb_nvmap, fb_info->win->surface);
- nvmap_free(fb_info->fb_nvmap, fb_info->win->surface);
+ if (fb_info->win->cur_handle) {
+ nvmap_unpin(fb_info->fb_nvmap, fb_info->win->cur_handle);
+ nvmap_free(fb_info->fb_nvmap, fb_info->win->cur_handle);
}
if (fb_info->fb_nvmap)
diff --git a/drivers/video/tegra/host/debug.c b/drivers/video/tegra/host/debug.c
index c2dfe3156df3..c1cfd6ee229c 100644
--- a/drivers/video/tegra/host/debug.c
+++ b/drivers/video/tegra/host/debug.c
@@ -48,19 +48,19 @@ static int nvhost_debug_handle_cmd(struct seq_file *s, u32 val, int *count)
}
case 0x1:
- seq_printf(s, "INCR(offset=%03x, [", val >> 16 & 0x3ff);
+ seq_printf(s, "INCR(offset=%03x, [", val >> 16 & 0xfff);
*count = val & 0xffff;
return NVHOST_DBG_STATE_DATA;
case 0x2:
- seq_printf(s, "NOMINCR(offset=%03x, [", val >> 16 & 0x3ff);
+ seq_printf(s, "NONINCR(offset=%03x, [", val >> 16 & 0xfff);
*count = val & 0xffff;
return NVHOST_DBG_STATE_DATA;
case 0x3:
mask = val & 0xffff;
seq_printf(s, "MASK(offset=%03x, mask=%03x, [",
- val >> 16 & 0x3ff, mask);
+ val >> 16 & 0xfff, mask);
*count = hweight16(mask);
return NVHOST_DBG_STATE_DATA;
@@ -100,6 +100,33 @@ static int nvhost_debug_handle_cmd(struct seq_file *s, u32 val, int *count)
}
}
+static void nvhost_debug_handle_word(struct seq_file *s, int *state, int *count,
+ unsigned long addr, int channel, u32 val)
+{
+ switch (*state) {
+ case NVHOST_DBG_STATE_CMD:
+ if (addr)
+ seq_printf(s, "%d: %08x: %08x:", channel, addr, val);
+ else
+ seq_printf(s, "%d: %08x:", channel, val);
+
+ *state = nvhost_debug_handle_cmd(s, val, count);
+ if (*state == NVHOST_DBG_STATE_DATA && *count == 0) {
+ *state = NVHOST_DBG_STATE_CMD;
+ seq_printf(s, "])\n");
+ }
+ break;
+
+ case NVHOST_DBG_STATE_DATA:
+ (*count)--;
+ seq_printf(s, "%08x%s", val, *count > 0 ? ", " : "])\n");
+ if (*count == 0)
+ *state = NVHOST_DBG_STATE_CMD;
+ break;
+ }
+}
+
+
static int nvhost_debug_show(struct seq_file *s, void *unused)
{
struct nvhost_master *m = s->private;
@@ -116,7 +143,8 @@ static int nvhost_debug_show(struct seq_file *s, void *unused)
unsigned start, end;
unsigned wr_ptr, rd_ptr;
int state;
- int count = 0;
+ int count;
+ u32 phys_addr, size;
dmaput = readl(regs + HOST1X_CHANNEL_DMAPUT);
dmaget = readl(regs + HOST1X_CHANNEL_DMAGET);
@@ -151,9 +179,35 @@ static int nvhost_debug_show(struct seq_file *s, void *unused)
break;
}
+ nvhost_cdma_find_gather(&m->channels[i].cdma, dmaget, &phys_addr, &size);
+
+ /* If dmaget is in the pushbuffer (should always be?),
+ * check if we're executing a fetch, and if so dump
+ * it. */
+ if (size) {
+ u32 offset = dmaget - m->channels[i].cdma.push_buffer.phys;
+ u32 map_base = phys_addr & PAGE_MASK;
+ u32 map_size = (size * 4 + PAGE_SIZE - 1) & PAGE_MASK;
+ u32 map_offset = phys_addr - map_base;
+ void *map_addr = ioremap_nocache(map_base, map_size);
+
+ if (map_addr) {
+ u32 ii;
+
+ seq_printf(s, "\n%d: gather (%d words)\n", i, size);
+ state = NVHOST_DBG_STATE_CMD;
+ for (ii = 0; ii < size; ii++) {
+ val = readl(map_addr + map_offset + ii*sizeof(u32));
+ nvhost_debug_handle_word(s, &state, &count, phys_addr + ii, i, val);
+ }
+ iounmap(map_addr);
+ }
+ }
+
fifostat = readl(regs + HOST1X_CHANNEL_FIFOSTAT);
if ((fifostat & 1 << 10) == 0 ) {
+ seq_printf(s, "\n%d: fifo:\n", i);
writel(0x0, m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
writel(1 << 31 | i << 16, m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
rd_ptr = readl(m->aperture + HOST1X_SYNC_CFPEEK_PTRS) & 0x1ff;
@@ -169,24 +223,7 @@ static int nvhost_debug_show(struct seq_file *s, void *unused)
writel(1 << 31 | i << 16 | rd_ptr, m->aperture + HOST1X_SYNC_CFPEEK_CTRL);
val = readl(m->aperture + HOST1X_SYNC_CFPEEK_READ);
- switch (state) {
- case NVHOST_DBG_STATE_CMD:
- seq_printf(s, "%d: %08x:", i, val);
-
- state = nvhost_debug_handle_cmd(s, val, &count);
- if (state == NVHOST_DBG_STATE_DATA && count == 0) {
- state = NVHOST_DBG_STATE_CMD;
- seq_printf(s, "])\n");
- }
- break;
-
- case NVHOST_DBG_STATE_DATA:
- count--;
- seq_printf(s, "%08x%s", val, count > 0 ? ", " : "])\n");
- if (count == 0)
- state = NVHOST_DBG_STATE_CMD;
- break;
- }
+ nvhost_debug_handle_word(s, &state, &count, 0, i, val);
if (rd_ptr == end)
rd_ptr = start;
@@ -199,6 +236,7 @@ static int nvhost_debug_show(struct seq_file *s, void *unused)
if (state == NVHOST_DBG_STATE_DATA)
seq_printf(s, ", ...])\n");
}
+
seq_printf(s, "\n");
}
diff --git a/drivers/video/tegra/host/nvhost_cdma.c b/drivers/video/tegra/host/nvhost_cdma.c
index 4b90456696ad..f27656bac07b 100644
--- a/drivers/video/tegra/host/nvhost_cdma.c
+++ b/drivers/video/tegra/host/nvhost_cdma.c
@@ -627,3 +627,24 @@ void nvhost_cdma_flush(struct nvhost_cdma *cdma)
}
mutex_unlock(&cdma->lock);
}
+
+/**
+ * Find the currently executing gather in the push buffer and return
+ * its physical address and size.
+ */
+void nvhost_cdma_find_gather(struct nvhost_cdma *cdma, u32 dmaget, u32 *addr, u32 *size)
+{
+ u32 offset = dmaget - cdma->push_buffer.phys;
+
+ *addr = *size = 0;
+
+ if (offset >= 8 && offset < cdma->push_buffer.cur) {
+ u32 *p = cdma->push_buffer.mapped + (offset - 8) / 4;
+
+ /* Make sure we have a gather */
+ if ((p[0] >> 28) == 6) {
+ *addr = p[1];
+ *size = p[0] & 0x3fff;
+ }
+ }
+}
diff --git a/drivers/video/tegra/host/nvhost_cdma.h b/drivers/video/tegra/host/nvhost_cdma.h
index 77493abe0e27..a7f17d0413d5 100644
--- a/drivers/video/tegra/host/nvhost_cdma.h
+++ b/drivers/video/tegra/host/nvhost_cdma.h
@@ -97,5 +97,7 @@ void nvhost_cdma_end(struct nvmap_client *user_nvmap,
struct nvmap_handle **handles, unsigned int nr_handles);
void nvhost_cdma_update(struct nvhost_cdma *cdma);
void nvhost_cdma_flush(struct nvhost_cdma *cdma);
+void nvhost_cdma_find_gather(struct nvhost_cdma *cdma, u32 dmaget,
+ u32 *addr, u32 *size);
#endif
diff --git a/drivers/video/tegra/nvmap/nvmap.c b/drivers/video/tegra/nvmap/nvmap.c
index 7419731a7c52..506aef8408a9 100644
--- a/drivers/video/tegra/nvmap/nvmap.c
+++ b/drivers/video/tegra/nvmap/nvmap.c
@@ -225,12 +225,17 @@ int nvmap_pin_ids(struct nvmap_client *client,
if (ref) {
atomic_inc(&ref->pin);
nvmap_handle_get(h[i]);
- } else if (!client->super && (h[i]->owner != client) &&
- !h[i]->global) {
- ret = -EPERM;
} else {
- nvmap_warn(client, "%s pinning unreferenced handle "
- "%p\n", current->group_leader->comm, h[i]);
+ struct nvmap_handle *verify;
+ nvmap_ref_unlock(client);
+ verify = nvmap_validate_get(client, ids[i]);
+ if (verify)
+ nvmap_warn(client, "%s pinning unreferenced "
+ "handle %p\n",
+ current->group_leader->comm, h[i]);
+ else
+ ret = -EPERM;
+ nvmap_ref_lock(client);
}
}
nvmap_ref_unlock(client);
diff --git a/drivers/video/tegra/nvmap/nvmap_dev.c b/drivers/video/tegra/nvmap/nvmap_dev.c
index b84a788dd33b..c6669ed86c24 100644
--- a/drivers/video/tegra/nvmap/nvmap_dev.c
+++ b/drivers/video/tegra/nvmap/nvmap_dev.c
@@ -353,6 +353,8 @@ struct nvmap_handle *nvmap_validate_get(struct nvmap_client *client,
if ((unsigned long)h == id) {
if (client->super || h->global || (h->owner == client))
h = nvmap_handle_get(h);
+ else
+ h = NULL;
spin_unlock(&client->dev->handle_lock);
return h;
}
@@ -696,9 +698,9 @@ static int nvmap_probe(struct platform_device *pdev)
dev->dev_user.parent = &pdev->dev;
dev->dev_super.minor = MISC_DYNAMIC_MINOR;
- dev->dev_super.name = "kvmap";
- dev->dev_user.fops = &nvmap_super_fops;
- dev->dev_user.parent = &pdev->dev;
+ dev->dev_super.name = "knvmap";
+ dev->dev_super.fops = &nvmap_super_fops;
+ dev->dev_super.parent = &pdev->dev;
dev->handles = RB_ROOT;
diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c
index eed3403db02d..21cbf9c4d85d 100644
--- a/drivers/video/tegra/nvmap/nvmap_handle.c
+++ b/drivers/video/tegra/nvmap/nvmap_handle.c
@@ -38,7 +38,7 @@
#include "nvmap_mru.h"
#define NVMAP_SECURE_HEAPS (NVMAP_HEAP_CARVEOUT_IRAM | NVMAP_HEAP_IOVMM)
-#define GFP_NVMAP (GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN)
+#define GFP_NVMAP (__GFP_HIGHMEM | __GFP_NOWARN)
/* handles may be arbitrarily large (16+MiB), and any handle allocated from
* the kernel (i.e., not a carveout handle) includes its array of pages. to
* preserve kmalloc space, if the array of pages exceeds PAGELIST_VMALLOC_MIN,
diff --git a/drivers/video/tegra/nvmap/nvmap_ioctl.c b/drivers/video/tegra/nvmap/nvmap_ioctl.c
index 9051803aa68d..b943065a44c0 100644
--- a/drivers/video/tegra/nvmap/nvmap_ioctl.c
+++ b/drivers/video/tegra/nvmap/nvmap_ioctl.c
@@ -459,7 +459,8 @@ static int cache_maint(struct nvmap_client *client, struct nvmap_handle *h,
}
if (h->flags == NVMAP_HANDLE_UNCACHEABLE ||
- h->flags == NVMAP_HANDLE_WRITE_COMBINE)
+ h->flags == NVMAP_HANDLE_WRITE_COMBINE ||
+ start == end)
goto out;
if (WARN_ON_ONCE(op == NVMAP_CACHE_OP_WB_INV))
@@ -607,7 +608,7 @@ static ssize_t rw_handle(struct nvmap_client *client, struct nvmap_handle *h,
return PTR_ERR(pte);
while (count--) {
- if (h_offs + elem_size >= h->size) {
+ if (h_offs + elem_size > h->size) {
nvmap_warn(client, "read/write outside of handle\n");
ret = -EFAULT;
break;