mirror of
https://github.com/armbian/build.git
synced 2025-08-09 20:56:57 +02:00
I have changed the way the patches are generated a bit. Instead of using orange-pi branch from megous tree for 6.6 kernel, I have used the following kernel branches a83t-suspend, af8133j, anx, audio, axp, cam, drm, err, fixes, mbus, modem, opi3, pb, pinetab, pp, ppkb, samuel, speed, tbs-a711, ths These branches were carefully chosen to include only allwinner related patches and remove importing of the rockchip related patches into the allwinner kernel. Following patches are modified to fix patch application failure - patches.armbian/arm64-dts-sun50i-h616-orangepi-zero2-reg_usb1_vbus-status-ok.patch - patches.armbian/arm64-dts-sun50i-h616-orangepi-zero2-Enable-GPU-mali.patch - patches.armbian/arm64-dts-allwinner-h616-Add-efuse_xlate-cpu-frequency-scaling-v1_6_2.patch - patches.armbian/arm64-dts-allwinner-h616-LED-green_power_on-red_status_heartbeat.patch - patches.armbian/arm64-dts-allwinner-overlay-Add-Overlays-for-sunxi64.patch - patches.armbian/arm64-dts-sun50i-h616-bigtreetech-cb1.patch Following patches are modified because of kernel api change to fix compilation failure - patches.armbian/drv-gpu-drm-sun4i-Add-HDMI-audio-sun4i-hdmi-encoder.patch - patches.armbian/drv-of-Device-Tree-Overlay-ConfigFS-interface.patch
275 lines
7.1 KiB
Diff
275 lines
7.1 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Alan <Alan>
|
|
Date: Sat, 20 May 2023 17:26:21 +0800
|
|
Subject: Add: ws2812 RGB driver for allwinner H616
|
|
|
|
---
|
|
drivers/leds/rgb/Kconfig | 7 +
|
|
drivers/leds/rgb/Makefile | 1 +
|
|
drivers/leds/rgb/leds-ws2812.c | 229 ++++++++++
|
|
3 files changed, 237 insertions(+)
|
|
|
|
diff --git a/drivers/leds/rgb/Kconfig b/drivers/leds/rgb/Kconfig
|
|
index 183bccc06cf3..855cf847ff93 100644
|
|
--- a/drivers/leds/rgb/Kconfig
|
|
+++ b/drivers/leds/rgb/Kconfig
|
|
@@ -52,3 +52,10 @@ config LEDS_MT6370_RGB
|
|
will be called "leds-mt6370-rgb".
|
|
|
|
endif # LEDS_CLASS_MULTICOLOR
|
|
+
|
|
+config LEDS_WS2812
|
|
+ tristate "WS2812 RGB support for allwinner H616"
|
|
+ depends on PINCTRL_SUN50I_H616
|
|
+
|
|
+ help
|
|
+ Say Y here if you want to use the WS2812.
|
|
\ No newline at end of file
|
|
diff --git a/drivers/leds/rgb/Makefile b/drivers/leds/rgb/Makefile
|
|
index c11cc56384e7..4a01f721c11a 100644
|
|
--- a/drivers/leds/rgb/Makefile
|
|
+++ b/drivers/leds/rgb/Makefile
|
|
@@ -4,3 +4,4 @@ obj-$(CONFIG_LEDS_GROUP_MULTICOLOR) += leds-group-multicolor.o
|
|
obj-$(CONFIG_LEDS_PWM_MULTICOLOR) += leds-pwm-multicolor.o
|
|
obj-$(CONFIG_LEDS_QCOM_LPG) += leds-qcom-lpg.o
|
|
obj-$(CONFIG_LEDS_MT6370_RGB) += leds-mt6370-rgb.o
|
|
+obj-$(CONFIG_LEDS_WS2812) += leds-ws2812.o
|
|
diff --git a/drivers/leds/rgb/leds-ws2812.c b/drivers/leds/rgb/leds-ws2812.c
|
|
new file mode 100644
|
|
index 000000000000..1af735ce8e4d
|
|
--- /dev/null
|
|
+++ b/drivers/leds/rgb/leds-ws2812.c
|
|
@@ -0,0 +1,229 @@
|
|
+// SPDX-License-Identifier: GPL-2.0-only
|
|
+/*
|
|
+ * Copyright (c) 2023, The Linux Foundation. All rights reserved.
|
|
+ */
|
|
+#include <linux/init.h>
|
|
+#include <linux/types.h>
|
|
+#include <linux/cdev.h>
|
|
+#include <linux/fs.h>
|
|
+#include <linux/device.h>
|
|
+#include <asm/uaccess.h>
|
|
+#include <linux/moduleparam.h>
|
|
+#include <linux/ioctl.h>
|
|
+#include <linux/version.h>
|
|
+#include <linux/errno.h>
|
|
+#include <linux/rbtree.h>
|
|
+#include <linux/ktime.h>
|
|
+#include <linux/string.h>
|
|
+#include <linux/mutex.h>
|
|
+#include <linux/time.h>
|
|
+#include <linux/hrtimer.h>
|
|
+#include <linux/pci.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/input.h>
|
|
+#include <linux/delay.h>
|
|
+#include <linux/slab.h>
|
|
+#include <linux/interrupt.h>
|
|
+#include <linux/irq.h>
|
|
+#include <linux/gpio.h>
|
|
+#include <linux/of_gpio.h>
|
|
+#include <linux/platform_device.h>
|
|
+#include <linux/miscdevice.h>
|
|
+#include <linux/uaccess.h>
|
|
+
|
|
+#define GPIO_BASE 0x0300B000
|
|
+#define GPIO_DAT_OFFSET(n) ((n)*0x0024 + 0x10)
|
|
+
|
|
+static uint32_t ws2812_pin = 0;
|
|
+static volatile uint32_t *ws2812_gpio_port;
|
|
+static volatile uint32_t ws2812_gpio_bit;
|
|
+static volatile uint32_t ws2812_set_val = 0;
|
|
+static volatile uint32_t ws2812_reset_val = 0;
|
|
+
|
|
+DEFINE_SPINLOCK(lock);
|
|
+
|
|
+// ws2812 reset
|
|
+static void ws2812_rst(void)
|
|
+{
|
|
+ *ws2812_gpio_port &= ~ws2812_gpio_bit;
|
|
+ udelay(200);// RES low voltage time, Above 50µs
|
|
+}
|
|
+
|
|
+static void ws2812_Write_24Bits(uint32_t grb)
|
|
+{
|
|
+ uint8_t i;
|
|
+ for (i = 0; i < 24; i++)
|
|
+ {
|
|
+ if (grb & 0x800000)
|
|
+ {
|
|
+ // loop for delay about 700ns
|
|
+ *ws2812_gpio_port = ws2812_set_val;
|
|
+ *ws2812_gpio_port = ws2812_set_val;
|
|
+ *ws2812_gpio_port = ws2812_set_val;
|
|
+ *ws2812_gpio_port = ws2812_set_val;
|
|
+ *ws2812_gpio_port = ws2812_set_val;
|
|
+ *ws2812_gpio_port = ws2812_set_val;
|
|
+ *ws2812_gpio_port = ws2812_set_val;
|
|
+ // loop for delay about 600ns
|
|
+ *ws2812_gpio_port = ws2812_reset_val;
|
|
+ *ws2812_gpio_port = ws2812_reset_val;
|
|
+ *ws2812_gpio_port = ws2812_reset_val;
|
|
+ *ws2812_gpio_port = ws2812_reset_val;
|
|
+ *ws2812_gpio_port = ws2812_reset_val;
|
|
+ *ws2812_gpio_port = ws2812_reset_val;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ // loop for delay about 200ns
|
|
+ *ws2812_gpio_port = ws2812_set_val;
|
|
+ *ws2812_gpio_port = ws2812_set_val;
|
|
+ // loop for delay about 800ns
|
|
+ *ws2812_gpio_port = ws2812_reset_val;
|
|
+ *ws2812_gpio_port = ws2812_reset_val;
|
|
+ *ws2812_gpio_port = ws2812_reset_val;
|
|
+ *ws2812_gpio_port = ws2812_reset_val;
|
|
+ *ws2812_gpio_port = ws2812_reset_val;
|
|
+ *ws2812_gpio_port = ws2812_reset_val;
|
|
+ *ws2812_gpio_port = ws2812_reset_val;
|
|
+ *ws2812_gpio_port = ws2812_reset_val;
|
|
+ }
|
|
+ grb <<= 1;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void ws2812_write_array(uint32_t *rgb, uint32_t cnt)
|
|
+{
|
|
+ uint32_t i = 0;
|
|
+ unsigned long flags;
|
|
+
|
|
+ for (i = 0; i < cnt; i++)
|
|
+ {
|
|
+ // rgb -> grb
|
|
+ rgb[i] = (((rgb[i] >> 16) & 0xff) << 8) | (((rgb[i] >> 8) & 0xff) << 16) | ((rgb[i]) & 0xff);
|
|
+ }
|
|
+
|
|
+ spin_lock_irqsave(&lock, flags);
|
|
+ ws2812_set_val = *ws2812_gpio_port | ws2812_gpio_bit;
|
|
+ ws2812_reset_val = *ws2812_gpio_port & (~ws2812_gpio_bit);
|
|
+ ws2812_rst();
|
|
+ for (i = 0; i < cnt; i++)
|
|
+ {
|
|
+ ws2812_Write_24Bits(rgb[i]);
|
|
+ }
|
|
+ spin_unlock_irqrestore(&lock, flags);
|
|
+}
|
|
+
|
|
+ssize_t ws2812_read(struct file *file, char __user *user, size_t bytesize, loff_t *this_loff_t)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+ssize_t ws2812_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos)
|
|
+{
|
|
+ uint32_t rgb[255];
|
|
+ unsigned long ret = 0;
|
|
+
|
|
+ if (count > 255 * 4) count = 255 * 4;
|
|
+ ret = copy_from_user(&rgb[0], user_buf, count);
|
|
+ if (ret < 0)
|
|
+ {
|
|
+ printk("copy_from_user fail!!!\n");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ ws2812_write_array((uint32_t *)rgb, count / 4);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int ws2812_open(struct inode *inode, struct file *file)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int ws2812_close(struct inode *inode, struct file *file)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static struct file_operations ws2812_ops = {
|
|
+ .owner = THIS_MODULE,
|
|
+ .open = ws2812_open,
|
|
+ .release = ws2812_close,
|
|
+ .write = ws2812_write,
|
|
+};
|
|
+
|
|
+static struct miscdevice ws2812_misc_dev = {
|
|
+ .minor = MISC_DYNAMIC_MINOR,
|
|
+ .name = "ws2812-led",
|
|
+ .fops = &ws2812_ops,
|
|
+};
|
|
+
|
|
+static int ws2812_probe(struct platform_device *pdev)
|
|
+{
|
|
+ int ret;
|
|
+ struct device_node *ws2812_gpio_node = pdev->dev.of_node;
|
|
+ uint32_t rgb_cnt = 0;
|
|
+ uint32_t rgb[255];
|
|
+
|
|
+ of_property_read_u32(ws2812_gpio_node, "rgb_cnt", &rgb_cnt);
|
|
+ if (rgb_cnt > 255)
|
|
+ rgb_cnt = 255;
|
|
+
|
|
+ of_property_read_u32_array(ws2812_gpio_node, "rgb_value", rgb, rgb_cnt);
|
|
+ ws2812_pin = of_get_named_gpio(ws2812_gpio_node, "gpios", 0);
|
|
+ if (!gpio_is_valid(ws2812_pin))
|
|
+ {
|
|
+ printk(KERN_ERR "ws2812: gpio: %d is invalid\n", ws2812_pin);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ ws2812_gpio_port = ioremap(GPIO_BASE + GPIO_DAT_OFFSET((ws2812_pin >> 5)), 4);
|
|
+ ws2812_gpio_bit = 1 << (ws2812_pin & 0x001F);
|
|
+
|
|
+ if (gpio_request(ws2812_pin, "ws2812-gpio"))
|
|
+ {
|
|
+ printk(KERN_ERR "ws2812: gpio %d request failed!\n", ws2812_pin);
|
|
+ gpio_free(ws2812_pin);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+ gpio_direction_output(ws2812_pin, 0);
|
|
+
|
|
+ ret = misc_register(&ws2812_misc_dev);
|
|
+ msleep(50);
|
|
+
|
|
+ ws2812_write_array(rgb, rgb_cnt);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int ws2812_remove(struct platform_device *pdev)
|
|
+{
|
|
+ misc_deregister(&ws2812_misc_dev);
|
|
+ gpio_free(ws2812_pin);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct of_device_id ws2812_of_match[] = {
|
|
+ {.compatible = "rgb-ws2812"},
|
|
+ {/* sentinel */}};
|
|
+
|
|
+MODULE_DEVICE_TABLE(of, ws2812_of_match);
|
|
+
|
|
+static struct platform_driver ws2812_driver = {
|
|
+ .probe = ws2812_probe,
|
|
+ .remove = ws2812_remove,
|
|
+ .driver = {
|
|
+ .name = "ws2812_ctl",
|
|
+ .of_match_table = ws2812_of_match,
|
|
+ },
|
|
+};
|
|
+
|
|
+module_platform_driver(ws2812_driver);
|
|
+
|
|
+MODULE_AUTHOR("MacLodge, Alan Ma <tech@biqu3d.com>");
|
|
+MODULE_DESCRIPTION("WS2812 RGB driver for Allwinner");
|
|
+MODULE_LICENSE("GPL");
|
|
+MODULE_ALIAS("platform:ws2812_ctl");
|
|
--
|
|
Armbian
|
|
|