Hi Thomas

>> From: Kerem Karabay <kek...@gmail.com>
>> 
>> The Touch Bars found on x86 Macs support two USB configurations: one
>> where the device presents itself as a HID keyboard and can display
>> predefined sets of keys, and one where the operating system has full
>> control over what is displayed. This commit adds support for the display
>> functionality of the second configuration.
>> 
>> Note that this driver has only been tested on T2 Macs, and only includes
>> the USB device ID for these devices. Testing on T1 Macs would be
>> appreciated.
>> 
>> Credit goes to @imbushuo on GitHub for reverse engineering most of the
>> protocol.
>> 
>> Signed-off-by: Kerem Karabay <kek...@gmail.com>
>> Signed-off-by: Aditya Garg <gargadity...@live.com>
>> ---
>> MAINTAINERS                       |   6 +
>> drivers/gpu/drm/tiny/Kconfig      |  12 +
>> drivers/gpu/drm/tiny/Makefile     |   1 +
>> drivers/gpu/drm/tiny/appletbdrm.c | 624 ++++++++++++++++++++++++++++++
>> 4 files changed, 643 insertions(+)
>> create mode 100644 drivers/gpu/drm/tiny/appletbdrm.c
>> 
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 8766f3e5e..2665e6c57 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -6889,6 +6889,12 @@ S: Supported
>> T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
>> F: drivers/gpu/drm/sun4i/sun8i*
>> +DRM DRIVER FOR APPLE TOUCH BARS
>> +M: Kerem Karabay <kek...@gmail.com>
>> +L: dri-devel@lists.freedesktop.org
>> +S: Maintained
>> +F: drivers/gpu/drm/tiny/appletbdrm.c
>> +
>> DRM DRIVER FOR ARM PL111 CLCD
>> S: Orphan
>> T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
>> diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig
>> index f6889f649..559a97bce 100644
>> --- a/drivers/gpu/drm/tiny/Kconfig
>> +++ b/drivers/gpu/drm/tiny/Kconfig
>> @@ -1,5 +1,17 @@
>> # SPDX-License-Identifier: GPL-2.0-only
>> +config DRM_APPLETBDRM
>> + tristate "DRM support for Apple Touch Bars"
>> + depends on DRM && USB && MMU
>> + select DRM_KMS_HELPER
>> + select DRM_GEM_SHMEM_HELPER
> 
> nit: Selects sorted alphabetically.
> 
>> + help
>> +   Say Y here if you want support for the display of Touch Bars on x86
>> +   MacBook Pros.
>> +
>> +   To compile this driver as a module, choose M here: the
>> +   module will be called appletbdrm.
>> +
>> config DRM_ARCPGU
>>  tristate "ARC PGU"
>>  depends on DRM && OF
>> diff --git a/drivers/gpu/drm/tiny/Makefile b/drivers/gpu/drm/tiny/Makefile
>> index 76dde89a0..9a1b412e7 100644
>> --- a/drivers/gpu/drm/tiny/Makefile
>> +++ b/drivers/gpu/drm/tiny/Makefile
>> @@ -1,5 +1,6 @@
>> # SPDX-License-Identifier: GPL-2.0-only
>> +obj-$(CONFIG_DRM_APPLETBDRM) += appletbdrm.o
>> obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o
>> obj-$(CONFIG_DRM_BOCHS) += bochs.o
>> obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o
>> diff --git a/drivers/gpu/drm/tiny/appletbdrm.c 
>> b/drivers/gpu/drm/tiny/appletbdrm.c
>> new file mode 100644
>> index 000000000..b9440ce00
>> --- /dev/null
>> +++ b/drivers/gpu/drm/tiny/appletbdrm.c
>> @@ -0,0 +1,624 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Apple Touch Bar DRM Driver
>> + *
>> + * Copyright (c) 2023 Kerem Karabay <kek...@gmail.com>
>> + */
>> +
>> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>> +
>> +#include <asm/unaligned.h>
>> +
>> +#include <linux/usb.h>
>> +#include <linux/module.h>
> 
> Include statements should be sorted alphabetically.
> 
>> +
>> +#include <drm/drm_drv.h>
>> +#include <drm/drm_fourcc.h>
>> +#include <drm/drm_probe_helper.h>
>> +#include <drm/drm_atomic_helper.h>
>> +#include <drm/drm_damage_helper.h>
>> +#include <drm/drm_format_helper.h>
>> +#include <drm/drm_gem_shmem_helper.h>
>> +#include <drm/drm_gem_atomic_helper.h>
>> +#include <drm/drm_simple_kms_helper.h>
>> +#include <drm/drm_gem_framebuffer_helper.h>
> 
> Sorting.
> 
>> +
>> +#define _APPLETBDRM_FOURCC(s) (((s)[0] << 24) | ((s)[1] << 16) | ((s)[2] << 
>> 8) | (s)[3])
>> +#define APPLETBDRM_FOURCC(s) _APPLETBDRM_FOURCC(#s)
>> +
>> +#define APPLETBDRM_PIXEL_FORMAT APPLETBDRM_FOURCC(RGBA) /* The actual 
>> format is BGR888 */
> 
> Pleasedon't call it FOURCC (because it isn't). Rather do something like
> 
> #define __APPLETBDRM_MSG_STR4(str4)    ((__le32 __force) /* bit shifting here 
> */)
> #define __APPLETBDRM_MSG_TOK4(tok4)    __APPLETBDRM_MSG_STR4(#tok4)
> 
> (two underscores)
> 
>> +#define APPLETBDRM_BITS_PER_PIXEL 24
>> +
>> +#define APPLETBDRM_MSG_CLEAR_DISPLAY APPLETBDRM_FOURCC(CLRD)
>> +#define APPLETBDRM_MSG_GET_INFORMATION APPLETBDRM_FOURCC(GINF)
>> +#define APPLETBDRM_MSG_UPDATE_COMPLETE APPLETBDRM_FOURCC(UDCL)
>> +#define APPLETBDRM_MSG_SIGNAL_READINESS APPLETBDRM_FOURCC(REDY)
> 
> Maybe infix all such constants with _MSG_ or _PROTO_ so that it's clear that 
> these are part of the device protocol.
> 
> I'd also change the style a bit to something like
> APPLETBDRM_MSG_REDY __APPLETBDRM_MSG_TOK4(REDY) /* device signals readiness */
> 
>> +
>> +#define APPLETBDRM_BULK_MSG_TIMEOUT 1000
>> +
>> +#define drm_to_adev(_drm) container_of(_drm, struct appletbdrm_device, drm)
>> +#define adev_to_udev(adev) interface_to_usbdev(to_usb_interface(adev->dev))
>> +
>> +struct appletbdrm_device {
>> + struct device *dev;
>> +
>> + u8 in_ep;
>> + u8 out_ep;
>> +
>> + u32 width;
>> + u32 height;
> 
> For software state, it's common to use regular types (unsigned int) without a 
> specific size.
> 
>> +
>> + struct drm_device drm;
>> + struct drm_display_mode mode;
>> + struct drm_connector connector;
>> + struct drm_simple_display_pipe pipe;
> 
> Simple-display pipe is deprecated. Please don't add any new drivers using it. 
> You can easily replace it by taking its code and data structures and inline 
> them into the driver. Change the naming to fit the driver and it should be 
> good.

I attempted to use atomic helper instead of simple display helpers for the 
driver, but for some reason, modprobing the driver results in “killed” message. 
I request you to comment upon what’s wrong here. The changes done are here:

—>8—

diff --git a/usr/src/apple-touchbar-advanced-0.1/appletbdrm.c 
b/usr/src/apple-touchbar-advanced-0.1/appletbdrm.c
index 7a74c8a..8b11a34 100644
--- a/usr/src/apple-touchbar-advanced-0.1/appletbdrm.c
+++ b/usr/src/apple-touchbar-advanced-0.1/appletbdrm.c
@@ -13,6 +13,8 @@
#include <linux/module.h>

#include <drm/drm_drv.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_plane_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_atomic_helper.h>
@@ -51,7 +53,9 @@ struct appletbdrm_device {
        struct drm_device drm;
        struct drm_display_mode mode;
        struct drm_connector connector;
-       struct drm_simple_display_pipe pipe;
+       struct drm_plane primary_plane;
+       struct drm_crtc crtc;
+       struct drm_encoder encoder;

        bool readiness_signal_received;
};
@@ -401,44 +405,82 @@ static int appletbdrm_connector_helper_get_modes(struct 
drm_connector *connector
        return drm_connector_helper_get_modes_fixed(connector, &adev->mode);
}

-static enum drm_mode_status appletbdrm_pipe_mode_valid(struct 
drm_simple_display_pipe *pipe,
-                                                      const struct 
drm_display_mode *mode)
+static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane 
*plane,
+                                                  struct drm_atomic_state 
*state)
{
-       struct drm_crtc *crtc = &pipe->crtc;
-       struct appletbdrm_device *adev = drm_to_adev(crtc->dev);
+       struct drm_plane_state *new_plane_state = 
drm_atomic_get_new_plane_state(state, plane);
+       struct drm_crtc *new_crtc = new_plane_state->crtc;
+       struct drm_crtc_state *new_crtc_state = NULL;
+       int ret;

-       return drm_crtc_helper_mode_valid_fixed(crtc, mode, &adev->mode);
+       if (new_crtc)
+               new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc);
+
+       ret = drm_atomic_helper_check_plane_state(new_plane_state, 
new_crtc_state,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 false, false);
+       if (ret)
+               return ret;
+       else if (!new_plane_state->visible)
+               return 0;
+
+       return 0;
}

-static void appletbdrm_pipe_disable(struct drm_simple_display_pipe *pipe)
+static void appletbdrm_primary_plane_helper_atomic_update(struct drm_plane 
*plane,
+                                                    struct drm_atomic_state 
*old_state)
{
-       struct appletbdrm_device *adev = drm_to_adev(pipe->crtc.dev);
+       struct appletbdrm_device *adev = drm_to_adev(plane->dev);
+       struct drm_device *drm = plane->dev;
+       struct drm_plane_state *plane_state = plane->state;
+       struct drm_plane_state *old_plane_state = 
drm_atomic_get_old_plane_state(old_state, plane);
        int idx;

-       if (!drm_dev_enter(&adev->drm, &idx))
+       if (!drm_dev_enter(drm, &idx))
                return;

-       appletbdrm_clear_display(adev);
+       appletbdrm_flush_damage(adev, old_plane_state, plane_state);

        drm_dev_exit(idx);
}

-static void appletbdrm_pipe_update(struct drm_simple_display_pipe *pipe,
-                                  struct drm_plane_state *old_state)
+static const struct drm_plane_helper_funcs 
appletbdrm_primary_plane_helper_funcs = {
+       DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
+       .atomic_check = appletbdrm_primary_plane_helper_atomic_check,
+       .atomic_update = appletbdrm_primary_plane_helper_atomic_update,
+};
+
+static const struct drm_plane_funcs appletbdrm_primary_plane_funcs = {
+       .update_plane = drm_atomic_helper_update_plane,
+       .disable_plane = drm_atomic_helper_disable_plane,
+       .destroy = drm_plane_cleanup,
+       DRM_GEM_SHADOW_PLANE_FUNCS,
+};
+
+static enum drm_mode_status appletbdrm_crtc_helper_mode_valid(struct drm_crtc 
*crtc,
+                                                         const struct 
drm_display_mode *mode)
+{
+       struct appletbdrm_device *adev = drm_to_adev(crtc->dev);
+
+       return drm_crtc_helper_mode_valid_fixed(crtc, mode, &adev->mode);
+}
+
+static void appletbdrm_crtc_helper_atomic_disable(struct drm_crtc *crtc,
+                                            struct drm_atomic_state 
*crtc_state)
{
-       struct drm_crtc *crtc = &pipe->crtc;
        struct appletbdrm_device *adev = drm_to_adev(crtc->dev);
        int idx;

-       if (!crtc->state->active || !drm_dev_enter(&adev->drm, &idx))
+       if (!drm_dev_enter(&adev->drm, &idx))
                return;

-       appletbdrm_flush_damage(adev, old_state, pipe->plane.state);
+       appletbdrm_clear_display(adev);

        drm_dev_exit(idx);
}

-static const u32 appletbdrm_formats[] = {
+static const u32 appletbdrm_primary_plane_formats[] = {
        DRM_FORMAT_BGR888,
        DRM_FORMAT_XRGB8888, /* emulated */
};
@@ -461,11 +503,22 @@ static const struct drm_connector_helper_funcs 
appletbdrm_connector_helper_funcs
        .get_modes = appletbdrm_connector_helper_get_modes,
};

-static const struct drm_simple_display_pipe_funcs appletbdrm_pipe_funcs = {
-       DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
-       .update = appletbdrm_pipe_update,
-       .disable = appletbdrm_pipe_disable,
-       .mode_valid = appletbdrm_pipe_mode_valid,
+static const struct drm_crtc_helper_funcs appletbdrm_crtc_helper_funcs = {
+       .mode_valid = appletbdrm_crtc_helper_mode_valid,
+       .atomic_disable = appletbdrm_crtc_helper_atomic_disable,
+};
+
+static const struct drm_crtc_funcs appletbdrm_crtc_funcs = {
+       .reset = drm_atomic_helper_crtc_reset,
+       .destroy = drm_crtc_cleanup,
+       .set_config = drm_atomic_helper_set_config,
+       .page_flip = drm_atomic_helper_page_flip,
+       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+static const struct drm_encoder_funcs appletbdrm_encoder_funcs = {
+       .destroy = drm_encoder_cleanup,
};

DEFINE_DRM_GEM_FOPS(appletbdrm_drm_fops);
@@ -484,10 +537,38 @@ static const struct drm_driver appletbdrm_drm_driver = {
static int appletbdrm_setup_mode_config(struct appletbdrm_device *adev)
{
        struct drm_connector *connector = &adev->connector;
+       struct drm_plane *primary_plane;
+       struct drm_crtc *crtc;
+       struct drm_encoder *encoder;
        struct drm_device *drm = &adev->drm;
        struct device *dev = adev->dev;
        int ret;

+       primary_plane = &adev->primary_plane;
+       ret = drm_universal_plane_init(drm, primary_plane, 0,
+                                      &appletbdrm_primary_plane_funcs,
+                                      appletbdrm_primary_plane_formats,
+                                      
ARRAY_SIZE(appletbdrm_primary_plane_formats),
+                                      NULL,
+                                      DRM_PLANE_TYPE_PRIMARY, NULL);
+       if (ret)
+               return ret;
+       drm_plane_helper_add(primary_plane, 
&appletbdrm_primary_plane_helper_funcs);
+
+       crtc = &adev->crtc;
+       ret = drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
+                                       &appletbdrm_crtc_funcs, NULL);
+       if (ret)
+               return ret;
+       drm_crtc_helper_add(crtc, &appletbdrm_crtc_helper_funcs);
+
+       encoder = &adev->encoder;
+       ret = drm_encoder_init(drm, encoder, &appletbdrm_encoder_funcs,
+                              DRM_MODE_ENCODER_DAC, NULL);
+       if (ret)
+               return ret;
+       encoder->possible_crtcs = drm_crtc_mask(crtc);
+
        ret = drmm_mode_config_init(drm);
        if (ret)
                return dev_err_probe(dev, ret, "Failed to initialize mode 
configuration\n");
@@ -530,13 +611,13 @@ static int appletbdrm_setup_mode_config(struct 
appletbdrm_device *adev)
        if (ret)
                return dev_err_probe(dev, ret, "Failed to set non-desktop 
property\n");

-       ret = drm_simple_display_pipe_init(drm, &adev->pipe, 
&appletbdrm_pipe_funcs,
-                                          appletbdrm_formats, 
ARRAY_SIZE(appletbdrm_formats),
-                                          NULL, &adev->connector);
+       ret = drm_connector_attach_encoder(connector, encoder);
+
        if (ret)
                return dev_err_probe(dev, ret, "Failed to initialize simple 
display pipe\n");

-       drm_plane_enable_fb_damage_clips(&adev->pipe.plane);
+       drm_plane_helper_add(primary_plane, 
&appletbdrm_primary_plane_helper_funcs);
+       drm_plane_enable_fb_damage_clips(&adev->primary_plane);

        drm_mode_config_reset(drm);


The commit history having both old and new revisions of the driver is here:

https://github.com/AdityaGarg8/apple-touchbar-drv/blob/atomic/usr/src/apple-touchbar-advanced-0.1/appletbdrm.c

Thanks
Aditya

Reply via email to