diff options
-rw-r--r-- | arch/arm/mach-tegra/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-ventana-panel.c | 325 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-ventana-pinmux.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-ventana-power.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-ventana.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-ventana.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/dc.h | 16 | ||||
-rw-r--r-- | arch/arm/mach-tegra/powergate.c | 1 | ||||
-rw-r--r-- | arch/arm/mm/Kconfig | 9 | ||||
-rw-r--r-- | arch/arm/mm/attrib_alloc.c | 2 | ||||
-rw-r--r-- | arch/arm/mm/mmu.c | 60 | ||||
-rw-r--r-- | drivers/spi/spi_tegra.c | 1 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc.c | 18 | ||||
-rw-r--r-- | drivers/video/tegra/fb.c | 233 | ||||
-rw-r--r-- | drivers/video/tegra/host/debug.c | 82 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_cdma.c | 21 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_cdma.h | 2 | ||||
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap.c | 15 | ||||
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap_dev.c | 8 | ||||
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap_handle.c | 2 | ||||
-rw-r--r-- | drivers/video/tegra/nvmap/nvmap_ioctl.c | 5 |
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; |