mirror of
https://github.com/ps5-linux/ps5-linux-patches.git
synced 2026-07-16 14:20:40 +00:00
Compare commits
3 Commits
v1.3
...
kernel-7.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e00c8a7d38 | ||
|
|
45c3a2ec19 | ||
|
|
61eb7c0f71 |
391
linux.patch
391
linux.patch
@@ -1505,7 +1505,7 @@ index e3a035c9fece..6eb67dd7b52c 100644
|
||||
if (r)
|
||||
return r;
|
||||
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
index 0aee65503642..1ca2bcd7755d 100644
|
||||
index 0aee65503642..3ae712111a93 100644
|
||||
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
||||
@@ -80,6 +80,10 @@
|
||||
@@ -1566,33 +1566,44 @@ index 0aee65503642..1ca2bcd7755d 100644
|
||||
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) ||
|
||||
(mode->flags & DRM_MODE_FLAG_DBLSCAN))
|
||||
return result;
|
||||
@@ -10458,6 +10479,9 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state,
|
||||
new_crtc_state, i) {
|
||||
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
|
||||
@@ -10889,12 +10910,58 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
||||
drm_atomic_helper_update_legacy_modeset_state(dev, state);
|
||||
drm_dp_mst_atomic_wait_for_dependencies(state);
|
||||
|
||||
+#ifdef CONFIG_X86_PS5
|
||||
+ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
|
||||
+ new_crtc_state, i) {
|
||||
+ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
|
||||
+#endif
|
||||
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
|
||||
|
||||
if (old_crtc_state->active &&
|
||||
@@ -10465,6 +10489,11 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state,
|
||||
drm_atomic_crtc_needs_modeset(new_crtc_state))) {
|
||||
manage_dm_interrupts(adev, acrtc, NULL);
|
||||
dc_stream_release(dm_old_crtc_state->stream);
|
||||
+#ifdef CONFIG_X86_PS5
|
||||
+ dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
|
||||
+
|
||||
+ if ((new_crtc_state->active &&
|
||||
+ (!old_crtc_state->active ||
|
||||
+ drm_atomic_crtc_needs_modeset(new_crtc_state))) ||
|
||||
+ (old_crtc_state->active &&
|
||||
+ (!new_crtc_state->active ||
|
||||
+ drm_atomic_crtc_needs_modeset(new_crtc_state)))) {
|
||||
+ if (dm_new_crtc_state->stream && dc_is_dp_signal(dm_new_crtc_state->stream->signal)) {
|
||||
+ sceHdmiInitVideoConfig();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
}
|
||||
+
|
||||
dm_state = dm_atomic_get_new_state(state);
|
||||
if (dm_state && dm_state->context) {
|
||||
dc_state = dm_state->context;
|
||||
amdgpu_dm_commit_streams(state, dc_state);
|
||||
}
|
||||
|
||||
@@ -11035,6 +11064,22 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
||||
dc_stream_retain(dm_new_crtc_state->stream);
|
||||
acrtc->dm_irq_params.stream = dm_new_crtc_state->stream;
|
||||
manage_dm_interrupts(adev, acrtc, dm_new_crtc_state);
|
||||
+#ifdef CONFIG_X86_PS5
|
||||
+ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
|
||||
+ new_crtc_state, i) {
|
||||
+ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
|
||||
+ dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
|
||||
+
|
||||
+ if (new_crtc_state->active &&
|
||||
+ (!old_crtc_state->active ||
|
||||
+ drm_atomic_crtc_needs_modeset(new_crtc_state))) {
|
||||
+ if (dm_new_crtc_state->stream && dc_is_dp_signal(dm_new_crtc_state->stream->signal)) {
|
||||
+ struct dc_stream_state *stream = dm_new_crtc_state->stream;
|
||||
+ int channels = 0;
|
||||
@@ -1607,10 +1618,13 @@ index 0aee65503642..1ca2bcd7755d 100644
|
||||
+ sceHdmiSetAudioConfig(channels);
|
||||
+ sceHdmiSetAudioMute(0);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
}
|
||||
/* Handle vrr on->off / off->on transitions */
|
||||
amdgpu_dm_handle_vrr_transition(dm_old_crtc_state, dm_new_crtc_state);
|
||||
+
|
||||
amdgpu_dm_update_hdcp(state);
|
||||
|
||||
/* Handle connector state changes */
|
||||
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
|
||||
index 896f4719cf7b..0eb818421a50 100644
|
||||
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
|
||||
@@ -1853,7 +1867,7 @@ new file mode 100644
|
||||
index 000000000000..e846b6b0edbc
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/phy/mts/mts.h
|
||||
@@ -0,0 +1,181 @@
|
||||
@@ -0,0 +1,186 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * PlayStation 5 Gigabit Ethernet driver
|
||||
@@ -1925,6 +1939,11 @@ index 000000000000..e846b6b0edbc
|
||||
+
|
||||
+#define GBE_COAL_VAL 0x10001388
|
||||
+
|
||||
+/* this chip has no intx pin and its msi sometimes never fires (cold boot). when
|
||||
+ * we detect that, the link_poll work becomes the only way to service the rings,
|
||||
+ * so it polls this often (ms) instead of once a second to stay responsive. */
|
||||
+#define GBE_POLL_FALLBACK_MS 10
|
||||
+
|
||||
+/* excludes bit2 (LINK) - polling link state avoids IRQ storm from autoneg pulses */
|
||||
+#define GBE_IER_MASK 0x5014fa
|
||||
+
|
||||
@@ -2040,7 +2059,7 @@ new file mode 100644
|
||||
index 000000000000..4250a25d7260
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/phy/mts/mts_main.c
|
||||
@@ -0,0 +1,810 @@
|
||||
@@ -0,0 +1,823 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * PlayStation 5 Gigabit Ethernet driver
|
||||
@@ -2515,26 +2534,32 @@ index 000000000000..4250a25d7260
|
||||
+{
|
||||
+ struct gbe_priv *p = container_of(to_delayed_work(work),
|
||||
+ struct gbe_priv, link_poll);
|
||||
+ unsigned long delay = HZ;
|
||||
+
|
||||
+ gbe_link_change(p);
|
||||
+
|
||||
+ /*
|
||||
+ * on a cold boot the chip sometimes just never fires its first irq and
|
||||
+ * napi sits there doing nothing. if the irq count hasnt moved since last tick,
|
||||
+ * we kick it by hand and re-arm the mask.
|
||||
+ * napi sits there doing nothing. if the irq count hasnt moved since last
|
||||
+ * tick the msi is dead -- kick napi by hand and re-arm the mask. msi is the
|
||||
+ * only irq source (no intx pin), so while it stays dead we keep polling fast
|
||||
+ * (GBE_POLL_FALLBACK_MS) instead of once a second, or interactive rx lags by
|
||||
+ * up to a second. as soon as real irqs start arriving we drop back to HZ.
|
||||
+ */
|
||||
+ if (netif_running(p->netdev) && p->cnt_irq == p->irq_watchdog) {
|
||||
+ napi_schedule(&p->napi);
|
||||
+ gbe_wr(p, GBE_REG_IER, GBE_IER_MASK);
|
||||
+ delay = max_t(unsigned long, 1, msecs_to_jiffies(GBE_POLL_FALLBACK_MS));
|
||||
+ }
|
||||
+ p->irq_watchdog = p->cnt_irq;
|
||||
+
|
||||
+ if (++p->poll_tick >= 10) {
|
||||
+ /* dump stats roughly every 10s regardless of the current poll cadence */
|
||||
+ if (++p->poll_tick >= 10 * HZ / delay) {
|
||||
+ gbe_dump_stats(p);
|
||||
+ p->poll_tick = 0;
|
||||
+ }
|
||||
+
|
||||
+ schedule_delayed_work(&p->link_poll, HZ);
|
||||
+ schedule_delayed_work(&p->link_poll, delay);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
@@ -2582,11 +2607,18 @@ index 000000000000..4250a25d7260
|
||||
+ rx_done = gbe_rx_poll(p, budget);
|
||||
+
|
||||
+ if (rx_done < budget) {
|
||||
+ u32 isr;
|
||||
+
|
||||
+ napi_complete_done(napi, rx_done);
|
||||
+ gbe_wr(p, GBE_REG_IER, GBE_IER_MASK);
|
||||
+ /* chip wont send a fresh msi for stuff that landed while ier was
|
||||
+ off, so re-check isr and re-kick or interrupts just freeze */
|
||||
+ if (gbe_rd(p, GBE_REG_ISR) & GBE_IER_MASK) {
|
||||
+ off, so re-check isr and re-kick or interrupts just freeze.
|
||||
+ ACK the causes (W1C) first: otherwise a latched/undelivered
|
||||
+ cause (the msi-silent cold-boot case) keeps this condition
|
||||
+ permanently true and spins napi at ~30k polls/s, pinning a cpu. */
|
||||
+ isr = gbe_rd(p, GBE_REG_ISR) & GBE_IER_MASK;
|
||||
+ if (isr) {
|
||||
+ gbe_wr(p, GBE_REG_ISR, isr);
|
||||
+ if (napi_schedule_prep(&p->napi)) {
|
||||
+ gbe_wr(p, GBE_REG_IER, 0);
|
||||
+ __napi_schedule(&p->napi);
|
||||
@@ -3282,11 +3314,11 @@ index b4707640e102..7b854e5bb8ff 100644
|
||||
|
||||
diff --git a/drivers/ps5/Makefile b/drivers/ps5/Makefile
|
||||
new file mode 100644
|
||||
index 000000000000..7acb030a4976
|
||||
index 000000000000..ff1bbbbf219c
|
||||
--- /dev/null
|
||||
+++ b/drivers/ps5/Makefile
|
||||
@@ -0,0 +1 @@
|
||||
+obj-y += spcie.o tpcie.o hdmi.o mp1.o
|
||||
+obj-y += spcie.o tpcie.o hdmi.o mp1.o buzzer.o
|
||||
diff --git a/drivers/ps5/autoservo_param.h b/drivers/ps5/autoservo_param.h
|
||||
new file mode 100644
|
||||
index 000000000000..d2c25e461bf7
|
||||
@@ -5195,6 +5227,303 @@ index 000000000000..d2c25e461bf7
|
||||
+};
|
||||
+
|
||||
+#endif /* _AUTOSERVO_PARAM_H */
|
||||
diff --git a/drivers/ps5/buzzer.c b/drivers/ps5/buzzer.c
|
||||
new file mode 100644
|
||||
index 000000000000..f48ad6f92534
|
||||
--- /dev/null
|
||||
+++ b/drivers/ps5/buzzer.c
|
||||
@@ -0,0 +1,291 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+
|
||||
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/miscdevice.h>
|
||||
+#include <linux/fs.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/uaccess.h>
|
||||
+#include <linux/input.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/kthread.h>
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/ps5.h>
|
||||
+
|
||||
+#define BUZZER_IOC_MAGIC 'B'
|
||||
+
|
||||
+#define PS5_BUZZ_SILENT 0
|
||||
+#define PS5_BUZZ_SHORT 1
|
||||
+#define PS5_BUZZ_ERROR 2
|
||||
+#define PS5_BUZZ_LONG 3
|
||||
+
|
||||
+struct ps5_buzzer_step {
|
||||
+ __u8 value;
|
||||
+ __u16 hold_ms;
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+struct ps5_buzzer_pattern {
|
||||
+ __u32 nsteps;
|
||||
+ struct ps5_buzzer_step steps[];
|
||||
+};
|
||||
+
|
||||
+#define PS5_BUZZER_BEEP _IOW(BUZZER_IOC_MAGIC, 1, __u8)
|
||||
+#define PS5_BUZZER_PLAY _IOW(BUZZER_IOC_MAGIC, 2, struct ps5_buzzer_pattern)
|
||||
+#define PS5_BUZZER_STOP _IO(BUZZER_IOC_MAGIC, 3)
|
||||
+
|
||||
+#define MAX_PATTERN_STEPS 1024
|
||||
+
|
||||
+static struct input_dev *snd_idev;
|
||||
+static struct task_struct *play_thread;
|
||||
+static DEFINE_MUTEX(play_lock);
|
||||
+
|
||||
+static int ps5_buzz_raw(u8 level)
|
||||
+{
|
||||
+ u8 buf[ICC_MSG_MAX_SIZE] = {};
|
||||
+ struct icc_msg *msg = (struct icc_msg *)buf;
|
||||
+
|
||||
+ if (level > PS5_BUZZ_LONG)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ msg->service_id = ICC_SERVICE_ID_INDICATOR;
|
||||
+ msg->msg_type = 0x00;
|
||||
+ msg->length = 0x20;
|
||||
+ msg->data[0] = level;
|
||||
+
|
||||
+ return icc_query(buf, buf);
|
||||
+}
|
||||
+
|
||||
+struct play_ctx {
|
||||
+ struct ps5_buzzer_step *steps;
|
||||
+ u32 nsteps;
|
||||
+};
|
||||
+
|
||||
+static int play_fn(void *data)
|
||||
+{
|
||||
+ struct play_ctx *ctx = data;
|
||||
+ u32 i;
|
||||
+
|
||||
+ for (i = 0; i < ctx->nsteps && !kthread_should_stop(); i++) {
|
||||
+ ps5_buzz_raw(ctx->steps[i].value);
|
||||
+ if (ctx->steps[i].hold_ms)
|
||||
+ msleep_interruptible(ctx->steps[i].hold_ms);
|
||||
+ }
|
||||
+
|
||||
+ kfree(ctx->steps);
|
||||
+ kfree(ctx);
|
||||
+
|
||||
+ mutex_lock(&play_lock);
|
||||
+ play_thread = NULL;
|
||||
+ mutex_unlock(&play_lock);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int play_start(struct ps5_buzzer_step *steps, u32 nsteps)
|
||||
+{
|
||||
+ struct play_ctx *ctx;
|
||||
+ struct task_struct *t;
|
||||
+
|
||||
+ mutex_lock(&play_lock);
|
||||
+ if (play_thread) {
|
||||
+ mutex_unlock(&play_lock);
|
||||
+ return -EBUSY;
|
||||
+ }
|
||||
+
|
||||
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
+ if (!ctx) {
|
||||
+ mutex_unlock(&play_lock);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ ctx->steps = steps;
|
||||
+ ctx->nsteps = nsteps;
|
||||
+
|
||||
+ t = kthread_run(play_fn, ctx, "ps5_buzz_play");
|
||||
+ if (IS_ERR(t)) {
|
||||
+ kfree(ctx);
|
||||
+ mutex_unlock(&play_lock);
|
||||
+ return PTR_ERR(t);
|
||||
+ }
|
||||
+ play_thread = t;
|
||||
+ mutex_unlock(&play_lock);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int play_stop(void)
|
||||
+{
|
||||
+ mutex_lock(&play_lock);
|
||||
+ if (play_thread) {
|
||||
+ kthread_stop(play_thread);
|
||||
+ play_thread = NULL;
|
||||
+ }
|
||||
+ mutex_unlock(&play_lock);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static ssize_t buzz_write(struct file *f, const char __user *ubuf,
|
||||
+ size_t n, loff_t *pos)
|
||||
+{
|
||||
+ char c;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (n < 1)
|
||||
+ return -EINVAL;
|
||||
+ if (get_user(c, ubuf))
|
||||
+ return -EFAULT;
|
||||
+ if (c < '0' || c > '3')
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ ret = ps5_buzz_raw(c - '0');
|
||||
+ return ret ? ret : n;
|
||||
+}
|
||||
+
|
||||
+static long buzz_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
|
||||
+{
|
||||
+ switch (cmd) {
|
||||
+ case PS5_BUZZER_BEEP: {
|
||||
+ u8 level;
|
||||
+ if (get_user(level, (u8 __user *)arg))
|
||||
+ return -EFAULT;
|
||||
+ return ps5_buzz_raw(level);
|
||||
+ }
|
||||
+ case PS5_BUZZER_PLAY: {
|
||||
+ struct ps5_buzzer_pattern hdr;
|
||||
+ struct ps5_buzzer_step *steps;
|
||||
+ size_t bytes;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (copy_from_user(&hdr, (void __user *)arg, sizeof(hdr)))
|
||||
+ return -EFAULT;
|
||||
+ if (!hdr.nsteps || hdr.nsteps > MAX_PATTERN_STEPS)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ bytes = hdr.nsteps * sizeof(struct ps5_buzzer_step);
|
||||
+ steps = kmalloc(bytes, GFP_KERNEL);
|
||||
+ if (!steps)
|
||||
+ return -ENOMEM;
|
||||
+ if (copy_from_user(steps,
|
||||
+ (void __user *)(arg + sizeof(hdr)), bytes)) {
|
||||
+ kfree(steps);
|
||||
+ return -EFAULT;
|
||||
+ }
|
||||
+ ret = play_start(steps, hdr.nsteps);
|
||||
+ if (ret)
|
||||
+ kfree(steps);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ case PS5_BUZZER_STOP:
|
||||
+ return play_stop();
|
||||
+ }
|
||||
+ return -ENOTTY;
|
||||
+}
|
||||
+
|
||||
+static const struct file_operations buzz_fops = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .write = buzz_write,
|
||||
+ .unlocked_ioctl = buzz_ioctl,
|
||||
+ .llseek = noop_llseek,
|
||||
+};
|
||||
+
|
||||
+static struct miscdevice buzz_misc = {
|
||||
+ .minor = MISC_DYNAMIC_MINOR,
|
||||
+ .name = "ps5_buzzer",
|
||||
+ .fops = &buzz_fops,
|
||||
+ .mode = 0660,
|
||||
+};
|
||||
+
|
||||
+static int snd_event(struct input_dev *dev, unsigned int type,
|
||||
+ unsigned int code, int value)
|
||||
+{
|
||||
+ if (type == EV_SND && code == SND_BELL)
|
||||
+ ps5_buzz_raw(value ? PS5_BUZZ_SHORT : PS5_BUZZ_SILENT);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static ssize_t beep_store(struct device *d, struct device_attribute *a,
|
||||
+ const char *buf, size_t n)
|
||||
+{
|
||||
+ u8 level;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (kstrtou8(buf, 0, &level))
|
||||
+ return -EINVAL;
|
||||
+ ret = ps5_buzz_raw(level);
|
||||
+ return ret ? ret : n;
|
||||
+}
|
||||
+static DEVICE_ATTR_WO(beep);
|
||||
+
|
||||
+static ssize_t stop_store(struct device *d, struct device_attribute *a,
|
||||
+ const char *buf, size_t n)
|
||||
+{
|
||||
+ play_stop();
|
||||
+ return n;
|
||||
+}
|
||||
+static DEVICE_ATTR_WO(stop);
|
||||
+
|
||||
+static struct attribute *buzz_attrs[] = {
|
||||
+ &dev_attr_beep.attr,
|
||||
+ &dev_attr_stop.attr,
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static const struct attribute_group buzz_attr_group = {
|
||||
+ .attrs = buzz_attrs,
|
||||
+};
|
||||
+
|
||||
+static int __init ps5_buzzer_init(void)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = misc_register(&buzz_misc);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = sysfs_create_group(&buzz_misc.this_device->kobj, &buzz_attr_group);
|
||||
+ if (ret)
|
||||
+ goto err_misc;
|
||||
+
|
||||
+ snd_idev = input_allocate_device();
|
||||
+ if (!snd_idev) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err_sysfs;
|
||||
+ }
|
||||
+ snd_idev->name = "PS5 Chassis Buzzer";
|
||||
+ snd_idev->phys = "ps5_buzzer/input0";
|
||||
+ snd_idev->id.bustype = BUS_VIRTUAL;
|
||||
+ snd_idev->event = snd_event;
|
||||
+ input_set_capability(snd_idev, EV_SND, SND_BELL);
|
||||
+
|
||||
+ ret = input_register_device(snd_idev);
|
||||
+ if (ret)
|
||||
+ goto err_input;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_input:
|
||||
+ input_free_device(snd_idev);
|
||||
+ snd_idev = NULL;
|
||||
+err_sysfs:
|
||||
+ sysfs_remove_group(&buzz_misc.this_device->kobj, &buzz_attr_group);
|
||||
+err_misc:
|
||||
+ misc_deregister(&buzz_misc);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void __exit ps5_buzzer_exit(void)
|
||||
+{
|
||||
+ play_stop();
|
||||
+ if (snd_idev)
|
||||
+ input_unregister_device(snd_idev);
|
||||
+ sysfs_remove_group(&buzz_misc.this_device->kobj, &buzz_attr_group);
|
||||
+ misc_deregister(&buzz_misc);
|
||||
+}
|
||||
+
|
||||
+module_init(ps5_buzzer_init);
|
||||
+module_exit(ps5_buzzer_exit);
|
||||
+
|
||||
+MODULE_AUTHOR("Armandas Kvietkus");
|
||||
+MODULE_DESCRIPTION("PlayStation 5 chassis piezo buzzer");
|
||||
+MODULE_LICENSE("GPL");
|
||||
diff --git a/drivers/ps5/hdmi.c b/drivers/ps5/hdmi.c
|
||||
new file mode 100644
|
||||
index 000000000000..8f094490d677
|
||||
|
||||
Reference in New Issue
Block a user