diff --git a/Documentation/devicetree/bindings/iommu/iommu.txt b/Documentation/devicetree/bindings/iommu/iommu.txt new file mode 100644 index 0000000..6ce759a --- /dev/null +++ b/Documentation/devicetree/bindings/iommu/iommu.txt @@ -0,0 +1,167 @@ +This document describes the generic device tree binding for IOMMUs and their +master(s). + + +IOMMU device node: +================== + +An IOMMU can provide the following services: + +* Remap address space to allow devices to access physical memory ranges that + they otherwise wouldn't be capable of accessing. + + Example: 32-bit DMA to 64-bit physical addresses + +* Implement scatter-gather at page level granularity so that the device does + not have to. + +* Provide system protection against "rogue" DMA by forcing all accesses to go + through the IOMMU and faulting when encountering accesses to unmapped + address regions. + +* Provide address space isolation between multiple contexts. + + Example: Virtualization + +Device nodes compatible with this binding represent hardware with some of the +above capabilities. + +IOMMUs can be single-master or multiple-master. Single-master IOMMU devices +typically have a fixed association to the master device, whereas multiple- +master IOMMU devices can translate accesses from more than one master. + +The device tree node of the IOMMU device's parent bus must contain a valid +"dma-ranges" property that describes how the physical address space of the +IOMMU maps to memory. An empty "dma-ranges" property means that there is a +1:1 mapping from IOMMU to memory. + +Required properties: +-------------------- +- #address-cells: The number of cells in an IOMMU specifier needed to encode + an address. +- #size-cells: The number of cells in an IOMMU specifier needed to represent + the length of an address range. + +Typical values for the above include: +- #address-cells = <0>, size-cells = <0>: Single master IOMMU devices are not + configurable and therefore no additional information needs to be encoded in + the specifier. This may also apply to multiple master IOMMU devices that do + not allow the association of masters to be configured. +- #address-cells = <1>, size-cells = <0>: Multiple master IOMMU devices may + need to be configured in order to enable translation for a given master. In + such cases the single address cell corresponds to the master device's ID. +- #address-cells = <2>, size-cells = <2>: Some IOMMU devices allow the DMA + window for masters to be configured. The first cell of the address in this + may contain the master device's ID for example, while the second cell could + contain the start of the DMA window for the given device. The length of the + DMA window is specified by two additional cells. + + +IOMMU master node: +================== + +Devices that access memory through an IOMMU are called masters. A device can +have multiple master interfaces (to one or more IOMMU devices). + +Required properties: +-------------------- +- iommus: A list of phandle and IOMMU specifier pairs that describe the IOMMU + master interfaces of the device. One entry in the list describes one master + interface of the device. + +When an "iommus" property is specified in a device tree node, the IOMMU will +be used for address translation. If a "dma-ranges" property exists in the +device's parent node it will be ignored. An exception to this rule is if the +referenced IOMMU is disabled, in which case the "dma-ranges" property of the +parent shall take effect. + +Optional properties: +-------------------- +- iommu-names: A list of names identifying each entry in the "iommus" + property. + + +Notes: +====== + +One possible extension to the above is to use an "iommus" property along with +a "dma-ranges" property in a bus device node (such as PCI host bridges). This +can be useful to describe how children on the bus relate to the IOMMU if they +are not explicitly listed in the device tree (e.g. PCI devices). However, the +requirements of that use-case haven't been fully determined yet. Implementing +this is therefore not recommended without further discussion and extension of +this binding. + + +Examples: +========= + +Single-master IOMMU: +-------------------- + + iommu { + #address-cells = <0>; + #size-cells = <0>; + }; + + master { + iommus = <&/iommu>; + }; + +Multiple-master IOMMU with fixed associations: +---------------------------------------------- + + /* multiple-master IOMMU */ + iommu { + /* + * Masters are statically associated with this IOMMU and + * address translation is always enabled. + */ + #address-cells = <0>; + #size-cells = <0>; + }; + + /* static association with IOMMU */ + master@1 { + reg = <1>; + iommus = <&/iommu>; + }; + + /* static association with IOMMU */ + master@2 { + reg = <2>; + iommus = <&/iommu>; + }; + +Multiple-master IOMMU: +---------------------- + + iommu { + /* the specifier represents the ID of the master */ + #address-cells = <1>; + #size-cells = <0>; + }; + + master { + /* device has master ID 42 in the IOMMU */ + iommus = <&/iommu 42>; + }; + +Multiple-master IOMMU with configurable DMA window: +--------------------------------------------------- + + / { + #address-cells = <1>; + #size-cells = <1>; + + iommu { + /* master ID, address of DMA window */ + #address-cells = <2>; + #size-cells = <2>; + }; + + master { + /* master ID 42, 4 GiB DMA window starting at 0 */ + iommus = <&/iommu 42 0 0x1 0x0>; + }; + }; diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts index e31fb61..cd1b1cf 100644 --- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts +++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts @@ -1619,6 +1619,36 @@ nvidia,sys-clock-req-active-high; }; + hda@0,70030000 { + status = "okay"; + }; + + padctl@0,7009f000 { + pinctrl-0 = <&padctl_default>; + pinctrl-names = "default"; + + padctl_default: pinmux { + usb3 { + nvidia,lanes = "pcie-0", "pcie-1"; + nvidia,function = "usb3"; + nvidia,iddq = <0>; + }; + + pcie { + nvidia,lanes = "pcie-2", "pcie-3", + "pcie-4"; + nvidia,function = "pcie"; + nvidia,iddq = <0>; + }; + + sata { + nvidia,lanes = "sata-0"; + nvidia,function = "sata"; + nvidia,iddq = <0>; + }; + }; + }; + /* SD card */ sdhci@0,700b0400 { status = "okay"; diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi index 6e6bc4e..3a7212a 100644 --- a/arch/arm/boot/dts/tegra124.dtsi +++ b/arch/arm/boot/dts/tegra124.dtsi @@ -449,6 +449,53 @@ clock-names = "pclk", "clk32k_in"; }; + smmu: iommu@0,70019010 { + compatible = "nvidia,tegra124-smmu"; + reg = <0x0 0x70019010 0x0 0x34 + 0x0 0x700191f0 0x0 0x10 + 0x0 0x70019228 0x0 0x58 + 0x0 0x70019600 0x0 0x4 + 0x0 0x700199b8 0x0 0x4 + 0x0 0x700199e0 0x0 0x18 + 0x0 0x70019a88 0x0 0x24>; + nvidia,#asids = <128>; + dma-window = <0x0 0x0 0x0 0x40000000>; + iommu-cells = <1>; + status = "disabled"; + }; + + memory-controller@0,70019000 { + compatible = "nvidia,tegra124-mc"; + reg = <0x0 0x70019000 0x0 0x1000>; + status = "disabled"; + }; + + hda@0,70030000 { + compatible = "nvidia,tegra124-hda", "nvidia,tegra30-hda"; + reg = <0x0 0x70030000 0x0 0x10000>; + interrupts = ; + clocks = <&tegra_car TEGRA124_CLK_HDA>, + <&tegra_car TEGRA124_CLK_HDA2HDMI>, + <&tegra_car TEGRA124_CLK_HDA2CODEC_2X>; + clock-names = "hda", "hda2hdmi", "hdacodec_2x"; + resets = <&tegra_car 125>, /* hda */ + <&tegra_car 128>, /* hda2hdmi */ + <&tegra_car 111>; /* hda2codec_2x */ + reset-names = "hda", "hda2hdmi", "hdacodec_2x"; + status = "disabled"; + }; + + padctl: padctl@0,7009f000 { + compatible = "nvidia,tegra124-xusb-padctl"; + reg = <0x0 0x7009f000 0x0 0x1000>; + resets = <&tegra_car 142>; + reset-names = "padctl"; + + #address-cells = <0>; + #size-cells = <0>; + #phy-cells = <1>; + }; + sdhci@0,700b0000 { compatible = "nvidia,tegra124-sdhci"; reg = <0x0 0x700b0000 0x0 0x200>; diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index e16999e..cc38e10 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -57,6 +57,7 @@ config ARCH_TEGRA_124_SOC select ARM_L1_CACHE_SHIFT_6 select HAVE_ARM_ARCH_TIMER select PINCTRL_TEGRA124 + select PINCTRL_TEGRA_XUSB help Support for NVIDIA Tegra T124 processor family, based on the ARM CortexA15MP CPU diff --git a/drivers/base/dd.c b/drivers/base/dd.c index e4ffbcf..8aa1c1e 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -287,6 +287,12 @@ static int really_probe(struct device *dev, struct device_driver *drv) dev->driver = drv; + /* + ret = of_iommu_attach(dev); + if (ret) + goto probe_failed; + */ + /* If using pinctrl, bind pins now before probing */ ret = pinctrl_bind_pins(dev); if (ret) diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index 80efe51..84463d3 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -1015,6 +1015,9 @@ static struct tegra_devclk devclks[] __initdata = { { .con_id = "fuse", .dt_id = TEGRA124_CLK_FUSE }, { .dev_id = "rtc-tegra", .dt_id = TEGRA124_CLK_RTC }, { .dev_id = "timer", .dt_id = TEGRA124_CLK_TIMER }, + { .con_id = "hda", .dt_id = TEGRA124_CLK_HDA }, + { .con_id = "hda2codec_2x", .dt_id = TEGRA124_CLK_HDA2CODEC_2X }, + { .con_id = "hda2hdmi", .dt_id = TEGRA124_CLK_HDA2HDMI }, }; static struct clk **clks; @@ -1369,6 +1372,8 @@ static struct tegra_clk_init_table init_table[] __initdata = { {TEGRA124_CLK_XUSB_HS_SRC, TEGRA124_CLK_PLL_U_60M, 60000000, 0}, {TEGRA124_CLK_XUSB_FALCON_SRC, TEGRA124_CLK_PLL_RE_OUT, 224000000, 0}, {TEGRA124_CLK_XUSB_HOST_SRC, TEGRA124_CLK_PLL_RE_OUT, 112000000, 0}, + {TEGRA124_CLK_HDA, TEGRA124_CLK_PLL_P, 102000000, 0}, + {TEGRA124_CLK_HDA2CODEC_2X, TEGRA124_CLK_PLL_P, 48000000, 0}, /* This MUST be the last entry. */ {TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0}, }; diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index fe94cc1..47e34c5 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1080,7 +1080,7 @@ EXPORT_SYMBOL(drm_encoder_cleanup); int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, - const uint32_t *formats, uint32_t format_count, + const uint32_t *formats, unsigned int format_count, enum drm_plane_type type) { int ret; @@ -1144,7 +1144,7 @@ EXPORT_SYMBOL(drm_universal_plane_init); int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, - const uint32_t *formats, uint32_t format_count, + const uint32_t *formats, unsigned int format_count, bool is_primary) { enum drm_plane_type type; @@ -3622,8 +3622,9 @@ done: return ret; } -static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length, - void *data) +static struct drm_property_blob * +drm_property_create_blob(struct drm_device *dev, size_t length, + const void *data) { struct drm_property_blob *blob; int ret; diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 08e33b8..dd97666 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -387,8 +387,11 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, err = aux->transfer(aux, &msg); mutex_unlock(&aux->hw_mutex); if (err < 0) { - if (err == -EBUSY) + if (err == -EBUSY || err == -ETIMEDOUT) { + DRM_DEBUG_KMS("%ps.transfer() failed: %d\n", + aux, err); continue; + } return err; } diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 6d13314..4aaaa03 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -318,7 +318,7 @@ EXPORT_SYMBOL(drm_primary_helper_funcs); */ struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev, const uint32_t *formats, - int num_formats) + unsigned int num_formats) { struct drm_plane *primary; int ret; diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 304ca8c..3d83480 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -660,7 +660,7 @@ int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data, * the driver is responsible for mapping the pages into the * importers address space for use with dma_buf itself. */ -struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages) +struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages) { struct sg_table *sg = NULL; int ret; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c index 7dd680f..82eb038 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c @@ -152,13 +152,17 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, end = (pte + num); if (unlikely(end >= max)) end = max; - len = end - pte; + + if (!big) + len = end - pte; + else + len = 1; vmm->map_sg(vma, pgt, mem, pte, len, list); num -= len; pte += len; - list += len; + list += len << bits; if (unlikely(end >= max)) { pde++; pte = 0; diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index 51a2cb1..ad34c50 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c @@ -27,12 +27,37 @@ #include "nouveau_drm.h" #include "nouveau_gem.h" +#include "subdev/fb.h" + struct sg_table *nouveau_gem_prime_get_sg_table(struct drm_gem_object *obj) { struct nouveau_bo *nvbo = nouveau_gem_object(obj); - int npages = nvbo->bo.num_pages; + struct nouveau_mem *mem = nvbo->bo.mem.mm_node; + unsigned int npages = nvbo->bo.num_pages; + struct sg_table *sgt; + + if (nvbo->bo.ttm) { + sgt = drm_prime_pages_to_sg(nvbo->bo.ttm->pages, npages); + } else { + struct page *page = phys_to_page(mem->offset); + + sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); + if (!sgt) + goto out; + + if (sg_alloc_table(sgt, 1, GFP_KERNEL)) { + kfree(sgt); + sgt = NULL; + goto out; + } + + sg_set_page(sgt->sgl, page, PAGE_SIZE, 0); + sg_dma_address(sgt->sgl) = mem->offset; + sg_dma_len(sgt->sgl) = mem->size * PAGE_SIZE; + } - return drm_prime_pages_to_sg(nvbo->bo.ttm->pages, npages); +out: + return sgt; } void *nouveau_gem_prime_vmap(struct drm_gem_object *obj) @@ -89,7 +114,11 @@ int nouveau_gem_prime_pin(struct drm_gem_object *obj) int ret; /* pin buffer into GTT */ +#if 0 ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_TT); +#else + ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM); +#endif if (ret) return -EINVAL; diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index ef40381..afcca04 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -18,6 +18,7 @@ struct tegra_dc_soc_info { bool supports_interlacing; bool supports_cursor; + bool supports_block_linear; }; struct tegra_plane { @@ -212,15 +213,44 @@ static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET); tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET); - if (window->tiled) { - value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV | - DC_WIN_BUFFER_ADDR_MODE_TILE; + if (dc->soc->supports_block_linear) { + unsigned long height = window->tiling.value; + + switch (window->tiling.mode) { + case TEGRA_BO_TILING_MODE_PITCH: + value = DC_WINBUF_SURFACE_KIND_PITCH; + break; + + case TEGRA_BO_TILING_MODE_TILED: + value = DC_WINBUF_SURFACE_KIND_TILED; + break; + + case TEGRA_BO_TILING_MODE_BLOCK: + value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) | + DC_WINBUF_SURFACE_KIND_BLOCK; + break; + } + + tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND); } else { - value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV | - DC_WIN_BUFFER_ADDR_MODE_LINEAR; - } + switch (window->tiling.mode) { + case TEGRA_BO_TILING_MODE_PITCH: + value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV | + DC_WIN_BUFFER_ADDR_MODE_LINEAR; + break; - tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE); + case TEGRA_BO_TILING_MODE_TILED: + value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV | + DC_WIN_BUFFER_ADDR_MODE_TILE; + break; + + case TEGRA_BO_TILING_MODE_BLOCK: + DRM_ERROR("hardware doesn't support block linear mode\n"); + return -EINVAL; + } + + tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE); + } value = WIN_ENABLE; @@ -288,6 +318,7 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, struct tegra_dc *dc = to_tegra_dc(crtc); struct tegra_dc_window window; unsigned int i; + int err; memset(&window, 0, sizeof(window)); window.src.x = src_x >> 16; @@ -301,7 +332,10 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, window.format = tegra_dc_format(fb->pixel_format, &window.swap); window.bits_per_pixel = fb->bits_per_pixel; window.bottom_up = tegra_fb_is_bottom_up(fb); - window.tiled = tegra_fb_is_tiled(fb); + + err = tegra_fb_get_tiling(fb, &window.tiling); + if (err < 0) + return err; for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) { struct tegra_bo *bo = tegra_fb_get_plane(fb, i); @@ -402,8 +436,14 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, { struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); unsigned int h_offset = 0, v_offset = 0; + struct tegra_bo_tiling tiling; unsigned int format, swap; unsigned long value; + int err; + + err = tegra_fb_get_tiling(fb, &tiling); + if (err < 0) + return err; tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); @@ -417,15 +457,44 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH); tegra_dc_writel(dc, swap, DC_WIN_BYTE_SWAP); - if (tegra_fb_is_tiled(fb)) { - value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV | - DC_WIN_BUFFER_ADDR_MODE_TILE; + if (dc->soc->supports_block_linear) { + unsigned long height = tiling.value; + + switch (tiling.mode) { + case TEGRA_BO_TILING_MODE_PITCH: + value = DC_WINBUF_SURFACE_KIND_PITCH; + break; + + case TEGRA_BO_TILING_MODE_TILED: + value = DC_WINBUF_SURFACE_KIND_TILED; + break; + + case TEGRA_BO_TILING_MODE_BLOCK: + value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) | + DC_WINBUF_SURFACE_KIND_BLOCK; + break; + } + + tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND); } else { - value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV | - DC_WIN_BUFFER_ADDR_MODE_LINEAR; - } + switch (tiling.mode) { + case TEGRA_BO_TILING_MODE_PITCH: + value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV | + DC_WIN_BUFFER_ADDR_MODE_LINEAR; + break; - tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE); + case TEGRA_BO_TILING_MODE_TILED: + value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV | + DC_WIN_BUFFER_ADDR_MODE_TILE; + break; + + case TEGRA_BO_TILING_MODE_BLOCK: + DRM_ERROR("hardware doesn't support block linear mode\n"); + return -EINVAL; + } + + tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE); + } /* make sure bottom-up buffers are properly displayed */ if (tegra_fb_is_bottom_up(fb)) { @@ -1277,16 +1346,19 @@ static const struct host1x_client_ops dc_client_ops = { static const struct tegra_dc_soc_info tegra20_dc_soc_info = { .supports_interlacing = false, .supports_cursor = false, + .supports_block_linear = false, }; static const struct tegra_dc_soc_info tegra30_dc_soc_info = { .supports_interlacing = false, .supports_cursor = false, + .supports_block_linear = false, }; static const struct tegra_dc_soc_info tegra124_dc_soc_info = { .supports_interlacing = true, .supports_cursor = true, + .supports_block_linear = true, }; static const struct of_device_id tegra_dc_of_match[] = { diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index 78c5fef..705c93b 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h @@ -428,6 +428,11 @@ #define DC_WINBUF_ADDR_V_OFFSET_NS 0x809 #define DC_WINBUF_UFLOW_STATUS 0x80a +#define DC_WINBUF_SURFACE_KIND 0x80b +#define DC_WINBUF_SURFACE_KIND_PITCH (0 << 0) +#define DC_WINBUF_SURFACE_KIND_TILED (1 << 0) +#define DC_WINBUF_SURFACE_KIND_BLOCK (2 << 0) +#define DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(x) (((x) & 0x7) << 4) #define DC_WINBUF_AD_UFLOW_STATUS 0xbca #define DC_WINBUF_BD_UFLOW_STATUS 0xdca diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 3396f9f..cd29063 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -451,11 +451,104 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data, return 0; } + +static int tegra_gem_set_tiling(struct drm_device *drm, void *data, + struct drm_file *file) +{ + struct drm_tegra_gem_set_tiling *args = data; + enum tegra_bo_tiling_mode mode; + struct drm_gem_object *gem; + unsigned long value = 0; + struct tegra_bo *bo; + + switch (args->mode) { + case DRM_TEGRA_GEM_TILING_MODE_PITCH: + mode = TEGRA_BO_TILING_MODE_PITCH; + + if (args->value != 0) + return -EINVAL; + + break; + + case DRM_TEGRA_GEM_TILING_MODE_TILED: + mode = TEGRA_BO_TILING_MODE_TILED; + + if (args->value != 0) + return -EINVAL; + + break; + + case DRM_TEGRA_GEM_TILING_MODE_BLOCK: + mode = TEGRA_BO_TILING_MODE_BLOCK; + + if (args->value > 5) + return -EINVAL; + + value = args->value; + break; + + default: + return -EINVAL; + } + + gem = drm_gem_object_lookup(drm, file, args->handle); + if (!gem) + return -EINVAL; + + bo = to_tegra_bo(gem); + + bo->tiling.mode = mode; + bo->tiling.value = value; + + drm_gem_object_unreference(gem); + + return 0; +} + +static int tegra_gem_get_tiling(struct drm_device *drm, void *data, + struct drm_file *file) +{ + struct drm_tegra_gem_get_tiling *args = data; + struct drm_gem_object *gem; + struct tegra_bo *bo; + int err = 0; + + gem = drm_gem_object_lookup(drm, file, args->handle); + if (!gem) + return -EINVAL; + + bo = to_tegra_bo(gem); + + switch (bo->tiling.mode) { + case TEGRA_BO_TILING_MODE_PITCH: + args->mode = DRM_TEGRA_GEM_TILING_MODE_PITCH; + args->value = 0; + break; + + case TEGRA_BO_TILING_MODE_TILED: + args->mode = DRM_TEGRA_GEM_TILING_MODE_TILED; + args->value = 0; + break; + + case TEGRA_BO_TILING_MODE_BLOCK: + args->mode = DRM_TEGRA_GEM_TILING_MODE_BLOCK; + args->value = bo->tiling.value; + break; + + default: + err = -EINVAL; + break; + } + + drm_gem_object_unreference(gem); + + return err; +} #endif static const struct drm_ioctl_desc tegra_drm_ioctls[] = { #ifdef CONFIG_DRM_TEGRA_STAGING - DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED | DRM_AUTH), + DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED), @@ -465,6 +558,8 @@ static const struct drm_ioctl_desc tegra_drm_ioctls[] = { DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, DRM_UNLOCKED), #endif }; diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 6b8fe9d..96d754e 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -19,6 +19,8 @@ #include #include +#include "gem.h" + struct reset_control; struct tegra_fb { @@ -160,7 +162,8 @@ struct tegra_dc_window { unsigned int stride[2]; unsigned long base[3]; bool bottom_up; - bool tiled; + + struct tegra_bo_tiling tiling; }; /* from dc.c */ @@ -279,7 +282,9 @@ int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link, struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, unsigned int index); bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer); -bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer); +int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer, + struct tegra_bo_tiling *tiling); +int tegra_drm_fb_prepare(struct drm_device *drm); int tegra_drm_fb_init(struct drm_device *drm); void tegra_drm_fb_exit(struct drm_device *drm); #ifdef CONFIG_DRM_TEGRA_FBDEV diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index 9798a70..3ae2287 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -46,14 +46,15 @@ bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer) return false; } -bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer) +int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer, + struct tegra_bo_tiling *tiling) { struct tegra_fb *fb = to_tegra_fb(framebuffer); - if (fb->planes[0]->flags & TEGRA_BO_TILED) - return true; + /* TODO: handle YUV formats? */ + *tiling = fb->planes[0]->tiling; - return false; + return 0; } static void tegra_fb_destroy(struct drm_framebuffer *framebuffer) diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index aa85b7b..c1e4e8b 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -126,7 +126,7 @@ struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size, goto err_mmap; if (flags & DRM_TEGRA_GEM_CREATE_TILED) - bo->flags |= TEGRA_BO_TILED; + bo->tiling.mode = TEGRA_BO_TILING_MODE_TILED; if (flags & DRM_TEGRA_GEM_CREATE_BOTTOM_UP) bo->flags |= TEGRA_BO_BOTTOM_UP; diff --git a/drivers/gpu/drm/tegra/gem.h b/drivers/gpu/drm/tegra/gem.h index 2f3fe96..43a25c8 100644 --- a/drivers/gpu/drm/tegra/gem.h +++ b/drivers/gpu/drm/tegra/gem.h @@ -16,8 +16,18 @@ #include #include -#define TEGRA_BO_TILED (1 << 0) -#define TEGRA_BO_BOTTOM_UP (1 << 1) +#define TEGRA_BO_BOTTOM_UP (1 << 0) + +enum tegra_bo_tiling_mode { + TEGRA_BO_TILING_MODE_PITCH, + TEGRA_BO_TILING_MODE_TILED, + TEGRA_BO_TILING_MODE_BLOCK, +}; + +struct tegra_bo_tiling { + enum tegra_bo_tiling_mode mode; + unsigned long value; +}; struct tegra_bo { struct drm_gem_object gem; @@ -26,6 +36,8 @@ struct tegra_bo { struct sg_table *sgt; dma_addr_t paddr; void *vaddr; + + struct tegra_bo_tiling tiling; }; static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem) diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile index 71160a2..4819a41 100644 --- a/drivers/memory/Makefile +++ b/drivers/memory/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_FSL_IFC) += fsl_ifc.o obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o obj-$(CONFIG_TEGRA30_MC) += tegra30-mc.o +obj-$(CONFIG_ARCH_TEGRA) += tegra124-mc.o diff --git a/drivers/memory/tegra124-mc.c b/drivers/memory/tegra124-mc.c new file mode 100644 index 0000000..a5ddaed --- /dev/null +++ b/drivers/memory/tegra124-mc.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +struct latency_allowance { + unsigned int reg; + unsigned int shift; + unsigned int mask; + unsigned int def; +}; + +struct memory_client { + unsigned int id; + const char *name; + + struct latency_allowance latency; +}; + +static const struct memory_client memory_clients[] = { + { + .id = 0x01, + .name = "display0a", + .latency = { + .reg = 0x2e8, + .shift = 0, + .mask = 0xff, + .def = 0xc2, + }, + }, { + .id = 0x02, + .name = "display0ab", + .latency = { + .reg = 0x2f4, + .shift = 0, + .mask = 0xff, + .def = 0xc6, + }, + }, { + .id = 0x03, + .name = "display0b", + .latency = { + .reg = 0x2e8, + .shift = 16, + .mask = 0xff, + .def = 0x50, + }, + }, { + .id = 0x04, + .name = "display0bb", + .latency = { + .reg = 0x2f4, + .shift = 16, + .mask = 0xff, + .def = 0x50, + }, + }, { + .id = 0x05, + .name = "display0c", + .latency = { + .reg = 0x2ec, + .shift = 0, + .mask = 0xff, + .def = 0x50, + }, + }, { + .id = 0x06, + .name = "display0cb", + .latency = { + .reg = 0x2f8, + .shift = 0, + .mask = 0xff, + .def = 0x50, + }, + }, { + .id = 0x10, + .name = "displayhc", + .latency = { + .reg = 0x2f0, + .shift = 0, + .mask = 0xff, + .def = 0x50, + }, + }, { + .id = 0x11, + .name = "displayhcb", + .latency = { + .reg = 0x2fc, + .shift = 0, + .mask = 0xff, + .def = 0x50, + }, + }, { + .id = 0x5a, + .name = "displayt", + .latency = { + .reg = 0x2f0, + .shift = 16, + .mask = 0xff, + .def = 0x50, + }, + }, { + .id = 0x73, + .name = "displayd", + .latency = { + .reg = 0x3c8, + .shift = 0, + .mask = 0xff, + .def = 0x50, + }, + }, +}; + +struct tegra124_mc { + void __iomem *base; +}; + +static const struct of_device_id tegra124_mc_of_match[] = { + { .compatible = "nvidia,tegra124-mc", }, + { } +}; + +static int tegra124_mc_probe(struct platform_device *pdev) +{ + struct tegra124_mc *mc; + struct resource *res; + unsigned int i; + + mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); + if (!mc) + return -ENOMEM; + + platform_set_drvdata(pdev, mc); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mc->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mc->base)) + return PTR_ERR(mc->base); + + for (i = 0; i < ARRAY_SIZE(memory_clients); i++) { + const struct latency_allowance *la = &memory_clients[i].latency; + u32 value; + + value = readl(mc->base + la->reg); + value &= ~(la->mask << la->shift); + value |= (la->def & la->mask) << la->shift; + writel(value, mc->base + la->reg); + } + + return 0; +} + +static int tegra124_mc_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver tegra124_mc_driver = { + .driver = { + .name = "tegra124-mc", + .of_match_table = tegra124_mc_of_match, + }, + .probe = tegra124_mc_probe, + .remove = tegra124_mc_remove, +}; +module_platform_driver(tegra124_mc_driver); + +MODULE_AUTHOR("Thierry Reding "); +MODULE_DESCRIPTION("NVIDIA Tegra124 Memory Controller driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 083cf37..1a16734 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -592,19 +592,6 @@ static void tegra_pcie_port_free(struct tegra_pcie_port *port) devm_kfree(pcie->dev, port); } -static void tegra_pcie_fixup_bridge(struct pci_dev *dev) -{ - u16 reg; - - if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) { - pci_read_config_word(dev, PCI_COMMAND, ®); - reg |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER | PCI_COMMAND_SERR); - pci_write_config_word(dev, PCI_COMMAND, reg); - } -} -DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_fixup_bridge); - /* Tegra PCIE root complex wrongly reports device class */ static void tegra_pcie_fixup_class(struct pci_dev *dev) { @@ -612,8 +599,6 @@ static void tegra_pcie_fixup_class(struct pci_dev *dev) } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf0, tegra_pcie_fixup_class); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf1, tegra_pcie_fixup_class); -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0e1c, tegra_pcie_fixup_class); -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0e1d, tegra_pcie_fixup_class); /* Tegra PCIE requires relaxed ordering */ static void tegra_pcie_relax_enable(struct pci_dev *dev) diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 8af71a8..0f4e7a5 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1472,7 +1472,7 @@ extern int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data, extern int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, dma_addr_t *addrs, int max_pages); -extern struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages); +extern struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages); extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg); int drm_gem_dumb_destroy(struct drm_file *file, diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 251b75e..a5ca1bb 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -187,7 +187,7 @@ struct drm_framebuffer { struct drm_property_blob { struct drm_mode_object base; struct list_head head; - unsigned int length; + size_t length; unsigned char data[]; }; @@ -910,13 +910,13 @@ extern int drm_universal_plane_init(struct drm_device *dev, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, const uint32_t *formats, - uint32_t format_count, + unsigned int format_count, enum drm_plane_type type); extern int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, unsigned long possible_crtcs, const struct drm_plane_funcs *funcs, - const uint32_t *formats, uint32_t format_count, + const uint32_t *formats, unsigned int format_count, bool is_primary); extern void drm_plane_cleanup(struct drm_plane *plane); extern void drm_plane_force_disable(struct drm_plane *plane); diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h index 52e6870..190eb9b 100644 --- a/include/drm/drm_plane_helper.h +++ b/include/drm/drm_plane_helper.h @@ -42,30 +42,29 @@ * planes. */ -extern int drm_plane_helper_check_update(struct drm_plane *plane, - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_rect *src, - struct drm_rect *dest, - const struct drm_rect *clip, - int min_scale, - int max_scale, - bool can_position, - bool can_update_disabled, - bool *visible); -extern int drm_primary_helper_update(struct drm_plane *plane, - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h); -extern int drm_primary_helper_disable(struct drm_plane *plane); -extern void drm_primary_helper_destroy(struct drm_plane *plane); +int drm_plane_helper_check_update(struct drm_plane *plane, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_rect *src, + struct drm_rect *dest, + const struct drm_rect *clip, + int min_scale, + int max_scale, + bool can_position, + bool can_update_disabled, + bool *visible); +int drm_primary_helper_update(struct drm_plane *plane, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h); +int drm_primary_helper_disable(struct drm_plane *plane); +void drm_primary_helper_destroy(struct drm_plane *plane); extern const struct drm_plane_funcs drm_primary_helper_funcs; -extern struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev, - const uint32_t *formats, - int num_formats); - +struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev, + const uint32_t *formats, + unsigned int num_formats); #endif diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h index b754821..14bec52 100644 --- a/include/uapi/drm/tegra_drm.h +++ b/include/uapi/drm/tegra_drm.h @@ -129,6 +129,24 @@ struct drm_tegra_submit { __u32 reserved[5]; /* future expansion */ }; +#define DRM_TEGRA_GEM_TILING_MODE_PITCH 0 +#define DRM_TEGRA_GEM_TILING_MODE_TILED 1 +#define DRM_TEGRA_GEM_TILING_MODE_BLOCK 2 + +struct drm_tegra_gem_set_tiling { + __u32 handle; + __u32 mode; + __u32 value; + __u32 pad; +}; + +struct drm_tegra_gem_get_tiling { + __u32 handle; + __u32 mode; + __u32 value; + __u32 pad; +}; + #define DRM_TEGRA_GEM_CREATE 0x00 #define DRM_TEGRA_GEM_MMAP 0x01 #define DRM_TEGRA_SYNCPT_READ 0x02 @@ -139,6 +157,8 @@ struct drm_tegra_submit { #define DRM_TEGRA_GET_SYNCPT 0x07 #define DRM_TEGRA_SUBMIT 0x08 #define DRM_TEGRA_GET_SYNCPT_BASE 0x09 +#define DRM_TEGRA_GEM_SET_TILING 0x0a +#define DRM_TEGRA_GEM_GET_TILING 0x0b #define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create) #define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap) @@ -150,5 +170,7 @@ struct drm_tegra_submit { #define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt) #define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit) #define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base) +#define DRM_IOCTL_TEGRA_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_TILING, struct drm_tegra_gem_set_tiling) +#define DRM_IOCTL_TEGRA_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_TILING, struct drm_tegra_gem_get_tiling) #endif diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index a26cc5d..584e0fc 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -548,7 +548,7 @@ static void get_prompt_str(struct gstr *r, struct property *prop, { int i, j; struct menu *submenu[8], *menu, *location = NULL; - struct jump_key *jump; + struct jump_key *jump = NULL; str_printf(r, _("Prompt: %s\n"), _(prop->text)); menu = prop->menu->parent;