diff options
author | He Yangxuan <yangxuan8282@gmail.com> | 2018-12-12 04:18:06 +0000 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2018-12-20 14:35:09 +0000 |
commit | 468ce5d3db5bea1bfc4d0b21ce0460bbc508c0ff (patch) | |
tree | eed21d01ea548aec8278a37ccf3a67357c56ed13 /testing/linux-amlogic/0017-soc-amlogic-add-meson-canvas-driver.patch | |
parent | 27ddcaeab2051aaf617a81eeddfa34fb6557e64a (diff) | |
download | aports-468ce5d3db5bea1bfc4d0b21ce0460bbc508c0ff.tar.bz2 aports-468ce5d3db5bea1bfc4d0b21ce0460bbc508c0ff.tar.xz |
testing/linux-amlogic: upgrade to 4.19.8
Diffstat (limited to 'testing/linux-amlogic/0017-soc-amlogic-add-meson-canvas-driver.patch')
-rw-r--r-- | testing/linux-amlogic/0017-soc-amlogic-add-meson-canvas-driver.patch | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/testing/linux-amlogic/0017-soc-amlogic-add-meson-canvas-driver.patch b/testing/linux-amlogic/0017-soc-amlogic-add-meson-canvas-driver.patch new file mode 100644 index 0000000000..4bb5731f30 --- /dev/null +++ b/testing/linux-amlogic/0017-soc-amlogic-add-meson-canvas-driver.patch @@ -0,0 +1,314 @@ +From 47756c823298bef3895fa2837c4b3e97062e9842 Mon Sep 17 00:00:00 2001 +From: Maxime Jourdan <maxi.jourdan@wanadoo.fr> +Date: Fri, 20 Apr 2018 13:17:07 +0200 +Subject: [PATCH] soc: amlogic: add meson-canvas driver + +Amlogic SoCs have a repository of 256 canvas which they use to +describe pixel buffers. + +They contain metadata like width, height, block mode, endianness [..] + +Many IPs within those SoCs like vdec/vpu rely on those canvas to read/write +pixels. + +Reviewed-by: Jerome Brunet <jbrunet@baylibre.com> +Tested-by: Neil Armstrong <narmstrong@baylibre.com> +Signed-off-by: Maxime Jourdan <mjourdan@baylibre.com> + +--- + drivers/soc/amlogic/Kconfig | 7 ++ + drivers/soc/amlogic/Makefile | 1 + + drivers/soc/amlogic/meson-canvas.c | 185 +++++++++++++++++++++++++++++++ + include/linux/soc/amlogic/meson-canvas.h | 65 +++++++++++ + 4 files changed, 258 insertions(+) + create mode 100644 drivers/soc/amlogic/meson-canvas.c + create mode 100644 include/linux/soc/amlogic/meson-canvas.h + +diff --git a/drivers/soc/amlogic/Kconfig b/drivers/soc/amlogic/Kconfig +index b04f6e4..2f282b4 100644 +--- a/drivers/soc/amlogic/Kconfig ++++ b/drivers/soc/amlogic/Kconfig +@@ -1,5 +1,12 @@ + menu "Amlogic SoC drivers" + ++config MESON_CANVAS ++ tristate "Amlogic Meson Canvas driver" ++ depends on ARCH_MESON || COMPILE_TEST ++ default n ++ help ++ Say yes to support the canvas IP for Amlogic SoCs. ++ + config MESON_GX_SOCINFO + bool "Amlogic Meson GX SoC Information driver" + depends on ARCH_MESON || COMPILE_TEST +diff --git a/drivers/soc/amlogic/Makefile b/drivers/soc/amlogic/Makefile +index 8fa3218..0ab16d3 100644 +--- a/drivers/soc/amlogic/Makefile ++++ b/drivers/soc/amlogic/Makefile +@@ -1,3 +1,4 @@ ++obj-$(CONFIG_MESON_CANVAS) += meson-canvas.o + obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o + obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o + obj-$(CONFIG_MESON_MX_SOCINFO) += meson-mx-socinfo.o +diff --git a/drivers/soc/amlogic/meson-canvas.c b/drivers/soc/amlogic/meson-canvas.c +new file mode 100644 +index 0000000..fce33ca +--- /dev/null ++++ b/drivers/soc/amlogic/meson-canvas.c +@@ -0,0 +1,185 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright (C) 2018 BayLibre, SAS ++ * Copyright (C) 2015 Amlogic, Inc. All rights reserved. ++ * Copyright (C) 2014 Endless Mobile ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/mfd/syscon.h> ++#include <linux/module.h> ++#include <linux/regmap.h> ++#include <linux/soc/amlogic/meson-canvas.h> ++#include <linux/of_address.h> ++#include <linux/of_platform.h> ++#include <linux/io.h> ++ ++#define NUM_CANVAS 256 ++ ++/* DMC Registers */ ++#define DMC_CAV_LUT_DATAL 0x00 ++ #define CANVAS_WIDTH_LBIT 29 ++ #define CANVAS_WIDTH_LWID 3 ++#define DMC_CAV_LUT_DATAH 0x04 ++ #define CANVAS_WIDTH_HBIT 0 ++ #define CANVAS_HEIGHT_BIT 9 ++ #define CANVAS_WRAP_BIT 22 ++ #define CANVAS_BLKMODE_BIT 24 ++ #define CANVAS_ENDIAN_BIT 26 ++#define DMC_CAV_LUT_ADDR 0x08 ++ #define CANVAS_LUT_WR_EN BIT(9) ++ #define CANVAS_LUT_RD_EN BIT(8) ++ ++struct meson_canvas { ++ struct device *dev; ++ void __iomem *reg_base; ++ spinlock_t lock; /* canvas device lock */ ++ u8 used[NUM_CANVAS]; ++}; ++ ++static void canvas_write(struct meson_canvas *canvas, u32 reg, u32 val) ++{ ++ writel_relaxed(val, canvas->reg_base + reg); ++} ++ ++static u32 canvas_read(struct meson_canvas *canvas, u32 reg) ++{ ++ return readl_relaxed(canvas->reg_base + reg); ++} ++ ++struct meson_canvas *meson_canvas_get(struct device *dev) ++{ ++ struct device_node *canvas_node; ++ struct platform_device *canvas_pdev; ++ ++ canvas_node = of_parse_phandle(dev->of_node, "amlogic,canvas", 0); ++ if (!canvas_node) ++ return ERR_PTR(-ENODEV); ++ ++ canvas_pdev = of_find_device_by_node(canvas_node); ++ if (!canvas_pdev) ++ return ERR_PTR(-EPROBE_DEFER); ++ ++ return dev_get_drvdata(&canvas_pdev->dev); ++} ++EXPORT_SYMBOL_GPL(meson_canvas_get); ++ ++int meson_canvas_config(struct meson_canvas *canvas, u8 canvas_index, ++ u32 addr, u32 stride, u32 height, ++ unsigned int wrap, ++ unsigned int blkmode, ++ unsigned int endian) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&canvas->lock, flags); ++ if (!canvas->used[canvas_index]) { ++ dev_err(canvas->dev, ++ "Trying to setup non allocated canvas %u\n", ++ canvas_index); ++ spin_unlock_irqrestore(&canvas->lock, flags); ++ return -EINVAL; ++ } ++ ++ canvas_write(canvas, DMC_CAV_LUT_DATAL, ++ ((addr + 7) >> 3) | ++ (((stride + 7) >> 3) << CANVAS_WIDTH_LBIT)); ++ ++ canvas_write(canvas, DMC_CAV_LUT_DATAH, ++ ((((stride + 7) >> 3) >> CANVAS_WIDTH_LWID) << ++ CANVAS_WIDTH_HBIT) | ++ (height << CANVAS_HEIGHT_BIT) | ++ (wrap << CANVAS_WRAP_BIT) | ++ (blkmode << CANVAS_BLKMODE_BIT) | ++ (endian << CANVAS_ENDIAN_BIT)); ++ ++ canvas_write(canvas, DMC_CAV_LUT_ADDR, ++ CANVAS_LUT_WR_EN | canvas_index); ++ ++ /* Force a read-back to make sure everything is flushed. */ ++ canvas_read(canvas, DMC_CAV_LUT_DATAH); ++ spin_unlock_irqrestore(&canvas->lock, flags); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(meson_canvas_config); ++ ++int meson_canvas_alloc(struct meson_canvas *canvas, u8 *canvas_index) ++{ ++ int i; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&canvas->lock, flags); ++ for (i = 0; i < NUM_CANVAS; ++i) { ++ if (!canvas->used[i]) { ++ canvas->used[i] = 1; ++ spin_unlock_irqrestore(&canvas->lock, flags); ++ *canvas_index = i; ++ return 0; ++ } ++ } ++ spin_unlock_irqrestore(&canvas->lock, flags); ++ ++ dev_err(canvas->dev, "No more canvas available\n"); ++ return -ENODEV; ++} ++EXPORT_SYMBOL_GPL(meson_canvas_alloc); ++ ++int meson_canvas_free(struct meson_canvas *canvas, u8 canvas_index) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&canvas->lock, flags); ++ if (!canvas->used[canvas_index]) { ++ dev_err(canvas->dev, ++ "Trying to free unused canvas %u\n", canvas_index); ++ spin_unlock_irqrestore(&canvas->lock, flags); ++ return -EINVAL; ++ } ++ canvas->used[canvas_index] = 0; ++ spin_unlock_irqrestore(&canvas->lock, flags); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(meson_canvas_free); ++ ++static int meson_canvas_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ struct meson_canvas *canvas; ++ struct device *dev = &pdev->dev; ++ ++ canvas = devm_kzalloc(dev, sizeof(*canvas), GFP_KERNEL); ++ if (!canvas) ++ return -ENOMEM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ canvas->reg_base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(canvas->reg_base)) ++ return PTR_ERR(canvas->reg_base); ++ ++ canvas->dev = dev; ++ spin_lock_init(&canvas->lock); ++ dev_set_drvdata(dev, canvas); ++ ++ return 0; ++} ++ ++static const struct of_device_id canvas_dt_match[] = { ++ { .compatible = "amlogic,canvas" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, canvas_dt_match); ++ ++static struct platform_driver meson_canvas_driver = { ++ .probe = meson_canvas_probe, ++ .driver = { ++ .name = "amlogic-canvas", ++ .of_match_table = canvas_dt_match, ++ }, ++}; ++module_platform_driver(meson_canvas_driver); ++ ++MODULE_DESCRIPTION("Amlogic Canvas driver"); ++MODULE_AUTHOR("Maxime Jourdan <mjourdan@baylibre.com>"); ++MODULE_LICENSE("GPL"); +diff --git a/include/linux/soc/amlogic/meson-canvas.h b/include/linux/soc/amlogic/meson-canvas.h +new file mode 100644 +index 0000000..b4dde2f +--- /dev/null ++++ b/include/linux/soc/amlogic/meson-canvas.h +@@ -0,0 +1,65 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright (C) 2018 BayLibre, SAS ++ */ ++#ifndef __SOC_MESON_CANVAS_H ++#define __SOC_MESON_CANVAS_H ++ ++#include <linux/kernel.h> ++ ++#define MESON_CANVAS_WRAP_NONE 0x00 ++#define MESON_CANVAS_WRAP_X 0x01 ++#define MESON_CANVAS_WRAP_Y 0x02 ++ ++#define MESON_CANVAS_BLKMODE_LINEAR 0x00 ++#define MESON_CANVAS_BLKMODE_32x32 0x01 ++#define MESON_CANVAS_BLKMODE_64x64 0x02 ++ ++#define MESON_CANVAS_ENDIAN_SWAP16 0x1 ++#define MESON_CANVAS_ENDIAN_SWAP32 0x3 ++#define MESON_CANVAS_ENDIAN_SWAP64 0x7 ++#define MESON_CANVAS_ENDIAN_SWAP128 0xf ++ ++struct meson_canvas; ++ ++/** ++ * meson_canvas_get() - get a canvas provider instance ++ * ++ * @dev: consumer device pointer ++ */ ++struct meson_canvas *meson_canvas_get(struct device *dev); ++ ++/** ++ * meson_canvas_alloc() - take ownership of a canvas ++ * ++ * @canvas: canvas provider instance retrieved from meson_canvas_get() ++ * @canvas_index: will be filled with the canvas ID ++ */ ++int meson_canvas_alloc(struct meson_canvas *canvas, u8 *canvas_index); ++ ++/** ++ * meson_canvas_free() - remove ownership from a canvas ++ * ++ * @canvas: canvas provider instance retrieved from meson_canvas_get() ++ * @canvas_index: canvas ID that was obtained via meson_canvas_alloc() ++ */ ++int meson_canvas_free(struct meson_canvas *canvas, u8 canvas_index); ++ ++/** ++ * meson_canvas_config() - configure a canvas ++ * ++ * @canvas: canvas provider instance retrieved from meson_canvas_get() ++ * @canvas_index: canvas ID that was obtained via meson_canvas_alloc() ++ * @addr: physical address to the pixel buffer ++ * @stride: width of the buffer ++ * @height: height of the buffer ++ * @wrap: undocumented ++ * @blkmode: block mode (linear, 32x32, 64x64) ++ * @endian: byte swapping (swap16, swap32, swap64, swap128) ++ */ ++int meson_canvas_config(struct meson_canvas *canvas, u8 canvas_index, ++ u32 addr, u32 stride, u32 height, ++ unsigned int wrap, unsigned int blkmode, ++ unsigned int endian); ++ ++#endif |