diff options
Diffstat (limited to 'testing/linux-amlogic/0021-soc-amlogic-add-meson-canvas-driver.patch')
-rw-r--r-- | testing/linux-amlogic/0021-soc-amlogic-add-meson-canvas-driver.patch | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/testing/linux-amlogic/0021-soc-amlogic-add-meson-canvas-driver.patch b/testing/linux-amlogic/0021-soc-amlogic-add-meson-canvas-driver.patch new file mode 100644 index 0000000000..226a7961a1 --- /dev/null +++ b/testing/linux-amlogic/0021-soc-amlogic-add-meson-canvas-driver.patch @@ -0,0 +1,280 @@ +From 8d7247813f02cad15a67980c2631d9ee37d7b76b Mon Sep 17 00:00:00 2001 +From: Maxime Jourdan <maxi.jourdan@wanadoo.fr> +Date: Wed, 1 Aug 2018 20:51:25 +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. + +Signed-off-by: Maxime Jourdan <maxi.jourdan@wanadoo.fr> +--- + drivers/soc/amlogic/Kconfig | 7 ++ + drivers/soc/amlogic/Makefile | 1 + + drivers/soc/amlogic/meson-canvas.c | 182 +++++++++++++++++++++++++++++++ + include/linux/soc/amlogic/meson-canvas.h | 37 +++++++ + 4 files changed, 227 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..5bd0498 100644 +--- a/drivers/soc/amlogic/Kconfig ++++ b/drivers/soc/amlogic/Kconfig +@@ -1,5 +1,12 @@ + menu "Amlogic SoC drivers" + ++config MESON_CANVAS ++ bool "Amlogic Meson Canvas driver" ++ depends on ARCH_MESON || COMPILE_TEST ++ default ARCH_MESON ++ help ++ Say yes to support the canvas IP within Amlogic Meson Soc family. ++ + 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..671eb89 +--- /dev/null ++++ b/drivers/soc/amlogic/meson-canvas.c +@@ -0,0 +1,182 @@ ++/* ++ * Copyright (C) 2018 Maxime Jourdan ++ * Copyright (C) 2016 BayLibre, SAS ++ * Author: Neil Armstrong <narmstrong@baylibre.com> ++ * Copyright (C) 2015 Amlogic, Inc. All rights reserved. ++ * Copyright (C) 2014 Endless Mobile ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include <linux/of_address.h> ++#include <linux/platform_device.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/regmap.h> ++#include <linux/mfd/syscon.h> ++#include <linux/soc/amlogic/meson-canvas.h> ++#include <asm/io.h> ++ ++#define NUM_CANVAS 256 ++ ++/* DMC Registers */ ++#define DMC_CAV_LUT_DATAL 0x48 /* 0x12 offset in data sheet */ ++ #define CANVAS_WIDTH_LBIT 29 ++ #define CANVAS_WIDTH_LWID 3 ++#define DMC_CAV_LUT_DATAH 0x4c /* 0x13 offset in data sheet */ ++ #define CANVAS_WIDTH_HBIT 0 ++ #define CANVAS_HEIGHT_BIT 9 ++ #define CANVAS_BLKMODE_BIT 24 ++#define DMC_CAV_LUT_ADDR 0x50 /* 0x14 offset in data sheet */ ++ #define CANVAS_LUT_WR_EN (0x2 << 8) ++ #define CANVAS_LUT_RD_EN (0x1 << 8) ++ ++struct meson_canvas { ++ struct device *dev; ++ struct regmap *regmap_dmc; ++ struct mutex lock; ++ u8 used[NUM_CANVAS]; ++}; ++ ++static struct meson_canvas canvas = { 0 }; ++ ++static int meson_canvas_setup(uint8_t canvas_index, uint32_t addr, ++ uint32_t stride, uint32_t height, ++ unsigned int wrap, ++ unsigned int blkmode, ++ unsigned int endian) ++{ ++ struct regmap *regmap = canvas.regmap_dmc; ++ u32 val; ++ ++ mutex_lock(&canvas.lock); ++ ++ if (!canvas.used[canvas_index]) { ++ dev_err(canvas.dev, ++ "Trying to setup non allocated canvas %u\n", ++ canvas_index); ++ mutex_unlock(&canvas.lock); ++ return -EINVAL; ++ } ++ ++ regmap_write(regmap, DMC_CAV_LUT_DATAL, ++ ((addr + 7) >> 3) | ++ (((stride + 7) >> 3) << CANVAS_WIDTH_LBIT)); ++ ++ regmap_write(regmap, DMC_CAV_LUT_DATAH, ++ ((((stride + 7) >> 3) >> CANVAS_WIDTH_LWID) << ++ CANVAS_WIDTH_HBIT) | ++ (height << CANVAS_HEIGHT_BIT) | ++ (wrap << 22) | ++ (blkmode << CANVAS_BLKMODE_BIT) | ++ (endian << 26)); ++ ++ regmap_write(regmap, DMC_CAV_LUT_ADDR, ++ CANVAS_LUT_WR_EN | canvas_index); ++ ++ /* Force a read-back to make sure everything is flushed. */ ++ regmap_read(regmap, DMC_CAV_LUT_DATAH, &val); ++ mutex_unlock(&canvas.lock); ++ ++ return 0; ++} ++ ++static int meson_canvas_alloc(uint8_t *canvas_index) ++{ ++ int i; ++ ++ mutex_lock(&canvas.lock); ++ for (i = 0; i < NUM_CANVAS; ++i) { ++ if (!canvas.used[i]) { ++ canvas.used[i] = 1; ++ mutex_unlock(&canvas.lock); ++ *canvas_index = i; ++ return 0; ++ } ++ } ++ mutex_unlock(&canvas.lock); ++ dev_err(canvas.dev, "No more canvas available\n"); ++ ++ return -ENODEV; ++} ++ ++static int meson_canvas_free(uint8_t canvas_index) ++{ ++ mutex_lock(&canvas.lock); ++ if (!canvas.used[canvas_index]) { ++ dev_err(canvas.dev, ++ "Trying to free unused canvas %u\n", canvas_index); ++ mutex_unlock(&canvas.lock); ++ return -EINVAL; ++ } ++ canvas.used[canvas_index] = 0; ++ mutex_unlock(&canvas.lock); ++ ++ return 0; ++} ++ ++static struct meson_canvas_platform_data canvas_platform_data = { ++ .alloc = meson_canvas_alloc, ++ .free = meson_canvas_free, ++ .setup = meson_canvas_setup, ++}; ++ ++static int meson_canvas_probe(struct platform_device *pdev) ++{ ++ struct regmap *regmap_dmc; ++ struct device *dev; ++ ++ dev = &pdev->dev; ++ ++ regmap_dmc = syscon_node_to_regmap(of_get_parent(dev->of_node)); ++ if (IS_ERR(regmap_dmc)) { ++ dev_err(&pdev->dev, "failed to get DMC regmap\n"); ++ return PTR_ERR(regmap_dmc); ++ } ++ ++ canvas.dev = dev; ++ canvas.regmap_dmc = regmap_dmc; ++ mutex_init(&canvas.lock); ++ ++ dev->platform_data = &canvas_platform_data; ++ ++ return 0; ++} ++ ++static int meson_canvas_remove(struct platform_device *pdev) ++{ ++ mutex_destroy(&canvas.lock); ++ return 0; ++} ++ ++static const struct of_device_id canvas_dt_match[] = { ++ { .compatible = "amlogic,meson-canvas" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, canvas_dt_match); ++ ++static struct platform_driver meson_canvas_driver = { ++ .probe = meson_canvas_probe, ++ .remove = meson_canvas_remove, ++ .driver = { ++ .name = "meson-canvas", ++ .of_match_table = canvas_dt_match, ++ }, ++}; ++module_platform_driver(meson_canvas_driver); ++ ++MODULE_ALIAS("platform:meson-canvas"); ++MODULE_DESCRIPTION("AMLogic Meson Canvas driver"); ++MODULE_AUTHOR("Maxime Jourdan <maxi.jourdan@wanadoo.fr>"); ++MODULE_LICENSE("GPL v2"); +diff --git a/include/linux/soc/amlogic/meson-canvas.h b/include/linux/soc/amlogic/meson-canvas.h +new file mode 100644 +index 0000000..af9e241 +--- /dev/null ++++ b/include/linux/soc/amlogic/meson-canvas.h +@@ -0,0 +1,37 @@ ++/* ++ * Copyright (c) 2018 Maxime Jourdan ++ * Author: Maxime Jourdan <maxi.jourdan@wanadoo.fr> ++ * ++ * 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. ++ * ++ * 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. ++ */ ++#ifndef MESON_CANVAS_H ++#define 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 ++ ++struct meson_canvas_platform_data { ++ int (*alloc)(uint8_t *canvas_index); ++ int (*free) (uint8_t canvas_index); ++ int (*setup)(uint8_t canvas_index, uint32_t addr, ++ uint32_t stride, uint32_t height, ++ unsigned int wrap, ++ unsigned int blkmode, ++ unsigned int endian); ++}; ++ ++#endif |