On 25/07/2024 02:47, Alex Lanzano wrote:
> Add support for the monochrome Sharp Memory LCDs.
> 
> Signed-off-by: Alex Lanzano <lanzano.a...@gmail.com>
> ---
>  MAINTAINERS                         |   8 +
>  drivers/gpu/drm/tiny/Kconfig        |  20 +
>  drivers/gpu/drm/tiny/Makefile       |   1 +
>  drivers/gpu/drm/tiny/sharp-memory.c | 742 ++++++++++++++++++++++++++++
>  4 files changed, 771 insertions(+)
>  create mode 100644 drivers/gpu/drm/tiny/sharp-memory.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 71b739b40921..d19893d25913 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -7123,6 +7123,14 @@ S:     Maintained
>  F:   Documentation/devicetree/bindings/display/panel/samsung,s6d7aa0.yaml
>  F:   drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c
>  
> +DRM DRIVER FOR SHARP MEMORY LCD
> +M:   Alex Lanzano <lanzano.a...@gmail.com>
> +S:   Maintained
> +T:   git git://anongit.freedesktop.org/drm/drm-misc
> +F:   Documentation/devicetree/bindings/display/sharp,sharp-memory.yaml
> +F:   drivers/gpu/drm/tiny/sharp-memory.c
> +F:   include/dt-bindings/display/sharp-memory.h
> +
>  DRM DRIVER FOR SITRONIX ST7586 PANELS
>  M:   David Lechner <da...@lechnology.com>
>  S:   Maintained
> diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig
> index f6889f649bc1..bc386954faa2 100644
> --- a/drivers/gpu/drm/tiny/Kconfig
> +++ b/drivers/gpu/drm/tiny/Kconfig
> @@ -186,6 +186,26 @@ config TINYDRM_REPAPER
>  
>         If M is selected the module will be called repaper.
>  
> +config TINYDRM_SHARP_MEMORY
> +     tristate "DRM support for Sharp Memory LCD panels"
> +     depends on DRM && SPI
> +     select DRM_GEM_DMA_HELPER
> +     select DRM_KMS_HELPER
> +     help
> +       DRM Driver for the following Sharp Memory Panels:
> +       * 1.00" Sharp Memory LCD (LS010B7DH04)
> +       * 1.10" Sharp Memory LCD (LS011B7DH03)
> +       * 1.20" Sharp Memory LCD (LS012B7DD01)
> +       * 1.28" Sharp Memory LCD (LS013B7DH03)
> +       * 1.26" Sharp Memory LCD (LS013B7DH05)
> +       * 1.80" Sharp Memory LCD (LS018B7DH02)
> +       * 2.70" Sharp Memory LCD (LS027B7DH01)
> +       * 2.70" Sharp Memory LCD (LS027B7DH01A)
> +       * 3.20" Sharp Memory LCD (LS032B7DD02)
> +       * 4.40" Sharp Memory LCD (LS044Q7DH01)
> +
> +       If M is selected the module will be called sharp_memory.
> +
>  config TINYDRM_ST7586
>       tristate "DRM support for Sitronix ST7586 display panels"
>       depends on DRM && SPI
> diff --git a/drivers/gpu/drm/tiny/Makefile b/drivers/gpu/drm/tiny/Makefile
> index 76dde89a044b..4aaf56f8707d 100644
> --- a/drivers/gpu/drm/tiny/Makefile
> +++ b/drivers/gpu/drm/tiny/Makefile
> @@ -14,5 +14,6 @@ obj-$(CONFIG_TINYDRM_ILI9341)               += ili9341.o
>  obj-$(CONFIG_TINYDRM_ILI9486)                += ili9486.o
>  obj-$(CONFIG_TINYDRM_MI0283QT)               += mi0283qt.o
>  obj-$(CONFIG_TINYDRM_REPAPER)                += repaper.o
> +obj-$(CONFIG_TINYDRM_SHARP_MEMORY)   += sharp-memory.o
>  obj-$(CONFIG_TINYDRM_ST7586)         += st7586.o
>  obj-$(CONFIG_TINYDRM_ST7735R)                += st7735r.o
> diff --git a/drivers/gpu/drm/tiny/sharp-memory.c 
> b/drivers/gpu/drm/tiny/sharp-memory.c
> new file mode 100644
> index 000000000000..5e61e348ce3a
> --- /dev/null
> +++ b/drivers/gpu/drm/tiny/sharp-memory.c
> @@ -0,0 +1,742 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/spi/spi.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/delay.h>
> +#include <linux/kthread.h>
> +#include <linux/bitrev.h>
> +#include <linux/pwm.h>
> +#include <linux/mutex.h>
> +
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_connector.h>
> +#include <drm/drm_damage_helper.h>
> +#include <drm/drm_drv.h>
> +#include <drm/drm_fb_dma_helper.h>
> +#include <drm/drm_fbdev_dma.h>
> +#include <drm/drm_format_helper.h>
> +#include <drm/drm_framebuffer.h>
> +#include <drm/drm_gem_atomic_helper.h>
> +#include <drm/drm_gem_dma_helper.h>
> +#include <drm/drm_gem_framebuffer_helper.h>
> +#include <drm/drm_managed.h>
> +#include <drm/drm_modes.h>
> +#include <drm/drm_rect.h>
> +#include <drm/drm_probe_helper.h>
> +
> +#include <dt-bindings/display/sharp-memory.h>
> +
> +#define SHARP_MODE_PERIOD 8
> +#define SHARP_ADDR_PERIOD 8
> +#define SHARP_DUMMY_PERIOD 8
> +
> +#define SHARP_MEMORY_DISPLAY_MAINTAIN_MODE 0
> +#define SHARP_MEMORY_DISPLAY_UPDATE_MODE 1
> +#define SHARP_MEMORY_DISPLAY_CLEAR_MODE 4
> +
> +enum sharp_memory_model {
> +     LS010B7DH04 = 1,
> +     LS011B7DH03,
> +     LS012B7DD01,
> +     LS013B7DH03,
> +     LS013B7DH05,
> +     LS018B7DH02,
> +     LS027B7DH01,
> +     LS027B7DH01A,
> +     LS032B7DD02,
> +     LS044Q7DH01,
> +};
> +
> +struct sharp_memory_device {
> +     struct drm_device drm;
> +     struct spi_device *spi;
> +
> +     const struct drm_display_mode *mode;
> +
> +     struct drm_crtc crtc;
> +     struct drm_plane plane;
> +     struct drm_encoder encoder;
> +     struct drm_connector connector;
> +
> +     struct gpio_desc *enable_gpio;
> +
> +     struct task_struct *sw_vcom_signal;
> +     struct pwm_device *pwm_vcom_signal;
> +
> +     uint32_t vcom_mode;
> +     uint8_t vcom;
> +
> +     uint32_t pitch;
> +     uint32_t tx_buffer_size;
> +     uint8_t *tx_buffer;
> +     struct mutex tx_mutex;
> +};
> +
> +static inline int sharp_memory_spi_write(struct spi_device *spi, void *buf, 
> size_t len)
> +{
> +     /* Reverse the bit order */
> +     for (uint8_t *b = buf; b < ((uint8_t *)buf) + len; ++b)
> +             *b = bitrev8(*b);
> +
> +     return spi_write(spi, buf, len);
> +}
> +
> +static inline struct sharp_memory_device *drm_to_sharp_memory_device(struct 
> drm_device *drm)
> +{
> +     return container_of(drm, struct sharp_memory_device, drm);
> +}
> +
> +DEFINE_DRM_GEM_DMA_FOPS(sharp_memory_fops);
> +
> +static const struct drm_driver sharp_memory_drm_driver = {
> +     .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
> +     .fops                   = &sharp_memory_fops,
> +     DRM_GEM_DMA_DRIVER_OPS_VMAP,
> +     .name                   = "sharp_memory_display",
> +     .desc                   = "Sharp Display Memory LCD",
> +     .date                   = "20231129",
> +     .major                  = 1,
> +     .minor                  = 0,
> +};
> +
> +static inline void sharp_memory_set_tx_buffer_mode(uint8_t *buffer, uint8_t 
> mode, uint8_t vcom)
> +{
> +
> +     *buffer = mode | (vcom << 1);
> +}
> +
> +static inline void sharp_memory_set_tx_buffer_addresses(uint8_t *buffer,
> +                                                     struct drm_rect clip,
> +                                                     uint32_t pitch)
> +{
> +     for (uint32_t line = 0; line < clip.y2; ++line)
> +             buffer[line * pitch] = line + 1;
> +
> +}
> +
> +static void sharp_memory_set_tx_buffer_data(uint8_t *buffer,
> +                                         struct drm_framebuffer *fb,
> +                                         struct drm_rect clip,
> +                                         uint32_t pitch,
> +                                         struct drm_format_conv_state 
> *fmtcnv_state)
> +{
> +     int ret;
> +     struct iosys_map dst, vmap;
> +     struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
> +
> +     ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
> +     if (ret)
> +             return;
> +
> +
> +     iosys_map_set_vaddr(&dst, buffer);
> +     iosys_map_set_vaddr(&vmap, dma_obj->vaddr);
> +
> +     drm_fb_xrgb8888_to_mono(&dst, &pitch, &vmap, fb, &clip, fmtcnv_state);
> +
> +     drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
> +}
> +
> +static int sharp_memory_update_display(struct sharp_memory_device *smd,
> +                                    struct drm_framebuffer *fb,
> +                                    struct drm_rect clip,
> +                                    struct drm_format_conv_state 
> *fmtcnv_state)
> +{
> +     int ret;
> +     uint32_t pitch = smd->pitch;
> +     uint8_t vcom = smd->vcom;
> +     uint8_t *tx_buffer = smd->tx_buffer;
> +     uint32_t tx_buffer_size = smd->tx_buffer_size;
> +
> +     mutex_lock(&smd->tx_mutex);
> +
> +     /* Populate the transmit buffer with frame data */
> +     sharp_memory_set_tx_buffer_mode(&tx_buffer[0],
> +                                     SHARP_MEMORY_DISPLAY_UPDATE_MODE, vcom);
> +     sharp_memory_set_tx_buffer_addresses(&tx_buffer[1], clip, pitch);
> +     sharp_memory_set_tx_buffer_data(&tx_buffer[2], fb, clip, pitch, 
> fmtcnv_state);
> +
> +     ret = sharp_memory_spi_write(smd->spi, tx_buffer, tx_buffer_size);
> +
> +     mutex_unlock(&smd->tx_mutex);
> +
> +     return ret;
> +}
> +
> +static int sharp_memory_maintain_display(struct sharp_memory_device *smd)
> +{
> +     int ret;
> +     uint8_t vcom = smd->vcom;
> +     uint8_t *tx_buffer = smd->tx_buffer;
> +
> +     mutex_lock(&smd->tx_mutex);
> +
> +     sharp_memory_set_tx_buffer_mode(&tx_buffer[0], 
> SHARP_MEMORY_DISPLAY_MAINTAIN_MODE, vcom);
> +     tx_buffer[1] = 0; // Write dummy data
> +     ret = sharp_memory_spi_write(smd->spi, tx_buffer, 2);
> +
> +     mutex_unlock(&smd->tx_mutex);
> +
> +     return ret;
> +}
> +
> +static int sharp_memory_clear_display(struct sharp_memory_device *smd)
> +{
> +     int ret;
> +     uint8_t vcom = smd->vcom;
> +     uint8_t *tx_buffer = smd->tx_buffer;
> +
> +     mutex_lock(&smd->tx_mutex);
> +
> +     sharp_memory_set_tx_buffer_mode(&tx_buffer[0], 
> SHARP_MEMORY_DISPLAY_CLEAR_MODE, vcom);
> +     tx_buffer[1] = 0; // write dummy data
> +     ret = sharp_memory_spi_write(smd->spi, tx_buffer, 2);
> +
> +     mutex_unlock(&smd->tx_mutex);
> +
> +     return ret;
> +}
> +
> +static void sharp_memory_fb_dirty(struct drm_framebuffer *fb, struct 
> drm_rect *rect,
> +                               struct drm_format_conv_state *fmtconv_state)
> +{
> +     struct drm_rect clip;
> +     struct sharp_memory_device *smd = drm_to_sharp_memory_device(fb->dev);
> +
> +     /* Always update a full line regardless of what is dirty */
> +     clip.x1 = 0;
> +     clip.x2 = fb->width;
> +     clip.y1 = rect->y1;
> +     clip.y2 = rect->y2;
> +
> +     sharp_memory_update_display(smd, fb, clip, fmtconv_state);
> +}
> +
> +static int sharp_memory_plane_atomic_check(struct drm_plane *plane,
> +                                        struct drm_atomic_state *state)
> +{
> +     struct drm_plane_state *plane_state = 
> drm_atomic_get_new_plane_state(state, plane);
> +     struct sharp_memory_device *smd;
> +     struct drm_crtc_state *crtc_state;
> +
> +     smd = container_of(plane, struct sharp_memory_device, plane);
> +     crtc_state = drm_atomic_get_new_crtc_state(state, &smd->crtc);
> +
> +     return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
> +                                                DRM_PLANE_NO_SCALING,
> +                                                DRM_PLANE_NO_SCALING,
> +                                                false, false);
> +}
> +
> +static void sharp_memory_plane_atomic_update(struct drm_plane *plane,
> +                                          struct drm_atomic_state *state)
> +{
> +
> +     struct drm_plane_state *old_state = 
> drm_atomic_get_old_plane_state(state, plane);
> +     struct drm_plane_state *plane_state = plane->state;
> +     struct drm_format_conv_state fmtcnv_state = DRM_FORMAT_CONV_STATE_INIT;
> +     struct sharp_memory_device *smd;
> +     struct drm_rect rect;
> +
> +     smd = container_of(plane, struct sharp_memory_device, plane);
> +     if (!smd->crtc.state->active)
> +             return;
> +
> +
> +     if (drm_atomic_helper_damage_merged(old_state, plane_state, &rect))
> +             sharp_memory_fb_dirty(plane_state->fb, &rect, &fmtcnv_state);
> +
> +     drm_format_conv_state_release(&fmtcnv_state);
> +}
> +
> +static const struct drm_plane_helper_funcs sharp_memory_plane_helper_funcs = 
> {
> +     .prepare_fb = drm_gem_plane_helper_prepare_fb,
> +     .atomic_check = sharp_memory_plane_atomic_check,
> +     .atomic_update = sharp_memory_plane_atomic_update,
> +};
> +
> +static bool sharp_memory_format_mod_supported(struct drm_plane *plane,
> +                                           uint32_t format,
> +                                           uint64_t modifier)
> +{
> +     return modifier == DRM_FORMAT_MOD_LINEAR;
> +}
> +
> +static const struct drm_plane_funcs sharp_memory_plane_funcs = {
> +     .update_plane = drm_atomic_helper_update_plane,
> +     .disable_plane = drm_atomic_helper_disable_plane,
> +     .destroy = drm_plane_cleanup,
> +     .reset = drm_atomic_helper_plane_reset,
> +     .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
> +     .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
> +     .format_mod_supported = sharp_memory_format_mod_supported,
> +};
> +
> +static enum drm_mode_status sharp_memory_crtc_mode_valid(struct drm_crtc 
> *crtc,
> +                                                      const struct 
> drm_display_mode *mode)
> +{
> +     struct sharp_memory_device *smd = drm_to_sharp_memory_device(crtc->dev);
> +
> +     return drm_crtc_helper_mode_valid_fixed(crtc, mode, smd->mode);
> +}
> +
> +static int sharp_memory_crtc_check(struct drm_crtc *crtc,
> +                                struct drm_atomic_state *state)
> +{
> +     struct drm_crtc_state *crtc_state = 
> drm_atomic_get_new_crtc_state(state, crtc);
> +     int ret;
> +
> +     if (!crtc_state->enable)
> +             goto out;
> +
> +     ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state);
> +     if (ret)
> +             return ret;
> +
> +out:
> +     return drm_atomic_add_affected_planes(state, crtc);
> +}
> +
> +static int sharp_memory_sw_vcom_signal_thread(void *data)
> +{
> +     struct sharp_memory_device *smd = data;
> +
> +     while (!kthread_should_stop()) {
> +             smd->vcom ^= 1; // Toggle vcom
> +             sharp_memory_maintain_display(smd);
> +             msleep(1000);
> +     }
> +
> +     return 0;
> +}
> +
> +static void sharp_memory_crtc_enable(struct drm_crtc *crtc,
> +                                  struct drm_atomic_state *state)
> +{
> +     struct pwm_state pwm_state;
> +     struct sharp_memory_device *smd = drm_to_sharp_memory_device(crtc->dev);
> +
> +     sharp_memory_clear_display(smd);
> +
> +     if (smd->enable_gpio)
> +             gpiod_set_value(smd->enable_gpio, 1);
> +
> +
> +     switch (smd->vcom_mode) {
> +     case SHARP_MEMORY_SOFTWARE_VCOM:
> +             smd->sw_vcom_signal = 
> kthread_run(sharp_memory_sw_vcom_signal_thread,
> +                                               smd, "sw_vcom_signal");
> +             break;
> +
> +     case SHARP_MEMORY_EXTERNAL_VCOM:
> +             break;
> +
> +     case SHARP_MEMORY_PWM_VCOM:
> +             pwm_get_state(smd->pwm_vcom_signal, &pwm_state);
> +             pwm_state.period =    1000000000;
> +             pwm_state.duty_cycle = 100000000;
> +             pwm_state.enabled = true;
> +             pwm_apply_state(smd->pwm_vcom_signal, &pwm_state);
> +             break;
> +     }
> +}
> +
> +static void sharp_memory_crtc_disable(struct drm_crtc *crtc,
> +                                   struct drm_atomic_state *state)
> +{
> +     struct sharp_memory_device *smd = drm_to_sharp_memory_device(crtc->dev);
> +
> +     sharp_memory_clear_display(smd);
> +
> +     if (smd->enable_gpio)
> +             gpiod_set_value(smd->enable_gpio, 0);
> +
> +
> +     switch (smd->vcom_mode) {
> +     case SHARP_MEMORY_SOFTWARE_VCOM:
> +             kthread_stop(smd->sw_vcom_signal);
> +             break;
> +
> +     case SHARP_MEMORY_EXTERNAL_VCOM:
> +             break;
> +
> +     case SHARP_MEMORY_PWM_VCOM:
> +             pwm_disable(smd->pwm_vcom_signal);
> +             break;
> +     }
> +}
> +
> +static const struct drm_crtc_helper_funcs sharp_memory_crtc_helper_funcs = {
> +     .mode_valid = sharp_memory_crtc_mode_valid,
> +     .atomic_check = sharp_memory_crtc_check,
> +     .atomic_enable = sharp_memory_crtc_enable,
> +     .atomic_disable = sharp_memory_crtc_disable,
> +};
> +
> +static const struct drm_crtc_funcs sharp_memory_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 sharp_memory_encoder_funcs = {
> +     .destroy = drm_encoder_cleanup,
> +};
> +
> +static int sharp_memory_connector_get_modes(struct drm_connector *connector)
> +{
> +     struct sharp_memory_device *smd = 
> drm_to_sharp_memory_device(connector->dev);
> +
> +     return drm_connector_helper_get_modes_fixed(connector, smd->mode);
> +}
> +
> +static const struct drm_connector_helper_funcs sharp_memory_connector_hfuncs 
> = {
> +     .get_modes = sharp_memory_connector_get_modes,
> +};
> +
> +static const struct drm_connector_funcs sharp_memory_connector_funcs = {
> +     .reset = drm_atomic_helper_connector_reset,
> +     .fill_modes = drm_helper_probe_single_connector_modes,
> +     .destroy = drm_connector_cleanup,
> +     .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +     .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +
> +};
> +
> +static const struct drm_mode_config_funcs sharp_memory_mode_config_funcs = {
> +     .fb_create = drm_gem_fb_create_with_dirty,
> +     .atomic_check = drm_atomic_helper_check,
> +     .atomic_commit = drm_atomic_helper_commit,
> +};
> +
> +static const struct spi_device_id sharp_memory_ids[] = {
> +     {"ls010b7dh04", LS010B7DH04},
> +     {"ls011b7dh03", LS011B7DH03},
> +     {"ls012b7dd01", LS012B7DD01},
> +     {"ls013b7dh03", LS013B7DH03},
> +     {"ls013b7dh05", LS013B7DH05},
> +     {"ls018b7dh02", LS018B7DH02},
> +     {"ls027b7dh01", LS027B7DH01},
> +     {"ls027b7dh01a", LS027B7DH01A},
> +     {"ls032b7dd02", LS032B7DD02},
> +     {"ls044q7dh01", LS044Q7DH01},
> +     {},
> +};
> +MODULE_DEVICE_TABLE(spi, sharp_memory_ids);
> +
> +static const struct of_device_id sharp_memory_of_match[] = {
> +     {.compatible = "sharp,ls010b7dh04"},

Both ID tables should be in sync. See not-so-recent IIO discussions and
commits.

> +     {.compatible = "sharp,ls011b7dh03"},
> +     {.compatible = "sharp,ls012b7dd01"},
> +     {.compatible = "sharp,ls013b7dh03"},
> +     {.compatible = "sharp,ls013b7dh05"},
> +     {.compatible = "sharp,ls018b7dh02"},
> +     {.compatible = "sharp,ls027b7dh01"},
> +     {.compatible = "sharp,ls027b7dh01a"},
> +     {.compatible = "sharp,ls032b7dd02"},
> +     {.compatible = "sharp,ls044q7dh01"},
> +     {},
> +};
> +MODULE_DEVICE_TABLE(of, sharp_memory_of_match);
> +
> +static const struct drm_display_mode sharp_memory_ls010b7dh04_mode = {
> +     DRM_SIMPLE_MODE(128, 128, 18, 18),
> +};
> +
> +static const struct drm_display_mode sharp_memory_ls011b7dh03_mode = {
> +     DRM_SIMPLE_MODE(160, 68, 25, 10),
> +};
> +
> +static const struct drm_display_mode sharp_memory_ls012b7dd01_mode = {
> +     DRM_SIMPLE_MODE(184, 38, 29, 6),
> +};
> +
> +static const struct drm_display_mode sharp_memory_ls013b7dh03_mode = {
> +     DRM_SIMPLE_MODE(128, 128, 23, 23),
> +};
> +
> +static const struct drm_display_mode sharp_memory_ls013b7dh05_mode = {
> +     DRM_SIMPLE_MODE(144, 168, 20, 24),
> +};
> +
> +static const struct drm_display_mode sharp_memory_ls018b7dh02_mode = {
> +     DRM_SIMPLE_MODE(230, 303, 27, 36),
> +};
> +
> +static const struct drm_display_mode sharp_memory_ls027b7dh01_mode = {
> +     DRM_SIMPLE_MODE(400, 240, 58, 35),
> +};
> +
> +static const struct drm_display_mode sharp_memory_ls032b7dd02_mode = {
> +     DRM_SIMPLE_MODE(336, 536, 42, 68),
> +};
> +
> +static const struct drm_display_mode sharp_memory_ls044q7dh01_mode = {
> +     DRM_SIMPLE_MODE(320, 240, 89, 67),
> +};
> +
> +static const uint32_t sharp_memory_formats[] = {
> +     DRM_FORMAT_XRGB8888,
> +};
> +
> +static inline enum sharp_memory_model 
> sharp_memory_model_from_device_id(struct spi_device *spi)
> +{
> +     const struct spi_device_id *spi_id = spi_get_device_id(spi);
> +
> +     return (enum sharp_memory_model)spi_id->driver_data;

No, use appropriate wrapper, do not re-implement spi_get_device_match_data.

> +}
> +
> +static int sharp_memory_pipe_init(struct drm_device *dev,
> +                               struct sharp_memory_device *smd,
> +                               const uint32_t *formats, unsigned int 
> format_count,
> +                               const uint64_t *format_modifiers)
> +{



Best regards,
Krzysztof

Reply via email to