diff mbox series

[v8,2/2] drm/panel: Add Boe Himax8279d MIPI-DSI LCD panel

Message ID 20190425032712.26011-1-jerry.han.hq@gmail.com (mailing list archive)
State New, archived
Headers show
Series [v8,1/2] dt-bindings: panel: Add Boe Himax8279d is 1200x1920, 4-lane MIPI-DSI LCD panel | expand

Commit Message

Jerry Han April 25, 2019, 3:27 a.m. UTC
Support Boe Himax8279d 8.0" 1200x1920 TFT LCD panel, it is a MIPI DSI
panel.

V8:
- Modify communication address

V7:
- Add the information of the reviewer
- Remove unnecessary delays, The udelay_range code gracefully returns
    without hitting the scheduler on a delay of 0. (Derek)
- Merge the same data structures, like display_mode and off_cmds (Derek)
- Optimize the processing of results returned by
    devm_gpiod_get_optional (Derek)

V6:
- Add the information of the reviewer (Sam)
- Delete unnecessary header files #include <linux/fb.h> (Sam)
- The config DRM_PANEL_BOE_HIMAX8279D appears twice. Drop one of them (Sam)
- ADD static, set_gpios function is not used outside this module (Sam)

V5:
- Added changelog

V4:
- Frefix all function maes with boe_ (Sam)
- Fsed "enable_gpio" replace "reset_gpio", Make it look clearer (Sam)
- Sort include lines alphabetically (Sam)
- Fixed entries in the makefile must be sorted alphabetically (Sam)
- Add send_mipi_cmds function to avoid duplicating the code (Sam)
- Add the necessary delay(reset_delay_t5) between reset and sending
    the initialization command (Rock wang)

V3:
- Remove unnecessary delays in sending initialization commands (Jitao Shi)

V2:
- Use SPDX identifier (Sam)
- Use necessary header files replace drmP.h (Sam)
- Delete unnecessary header files #include <linux/err.h> (Sam)
- Specifies a GPIOs array to control the reset timing,
    instead of reading "dsi-reset-sequence" data from DTS (Sam)
- Delete backlight_disable() function when already disabled (Sam)
- Use devm_of_find_backlight() replace of_find_backlight_by_node() (Sam)
- Move the necessary data in the DTS to the current file,
    like porch, display_mode and Init code etc. (Sam)
- Add compatible device "boe,himax8279d10p" (Sam)

Signed-off-by: Jerry Han <jerry.han.hq@gmail.com>
Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
Reviewed-by: Derek Basehore <dbasehore@chromium.org>
Cc: Jitao Shi <jitao.shi@mediatek.com>
Cc: Rock wang <rock_wang@himax.com.cn>
---
 MAINTAINERS                                  |    6 +
 drivers/gpu/drm/panel/Kconfig                |   11 +
 drivers/gpu/drm/panel/Makefile               |    1 +
 drivers/gpu/drm/panel/panel-boe-himax8279d.c | 1050 ++++++++++++++++++
 4 files changed, 1068 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-boe-himax8279d.c

Comments

Jerry Han April 25, 2019, 3:35 a.m. UTC | #1
Hi Thierry Reding:

*Could you please help to check whether there is any problem with the
sign-off identity**?*

*Thanks*

Jerry Han <jerry.han.hq@gmail.com> 于2019年4月25日周四 上午11:27写道:

> Support Boe Himax8279d 8.0" 1200x1920 TFT LCD panel, it is a MIPI DSI
> panel.
>
> V8:
> - Modify communication address
>
> V7:
> - Add the information of the reviewer
> - Remove unnecessary delays, The udelay_range code gracefully returns
>     without hitting the scheduler on a delay of 0. (Derek)
> - Merge the same data structures, like display_mode and off_cmds (Derek)
> - Optimize the processing of results returned by
>     devm_gpiod_get_optional (Derek)
>
> V6:
> - Add the information of the reviewer (Sam)
> - Delete unnecessary header files #include <linux/fb.h> (Sam)
> - The config DRM_PANEL_BOE_HIMAX8279D appears twice. Drop one of them (Sam)
> - ADD static, set_gpios function is not used outside this module (Sam)
>
> V5:
> - Added changelog
>
> V4:
> - Frefix all function maes with boe_ (Sam)
> - Fsed "enable_gpio" replace "reset_gpio", Make it look clearer (Sam)
> - Sort include lines alphabetically (Sam)
> - Fixed entries in the makefile must be sorted alphabetically (Sam)
> - Add send_mipi_cmds function to avoid duplicating the code (Sam)
> - Add the necessary delay(reset_delay_t5) between reset and sending
>     the initialization command (Rock wang)
>
> V3:
> - Remove unnecessary delays in sending initialization commands (Jitao Shi)
>
> V2:
> - Use SPDX identifier (Sam)
> - Use necessary header files replace drmP.h (Sam)
> - Delete unnecessary header files #include <linux/err.h> (Sam)
> - Specifies a GPIOs array to control the reset timing,
>     instead of reading "dsi-reset-sequence" data from DTS (Sam)
> - Delete backlight_disable() function when already disabled (Sam)
> - Use devm_of_find_backlight() replace of_find_backlight_by_node() (Sam)
> - Move the necessary data in the DTS to the current file,
>     like porch, display_mode and Init code etc. (Sam)
> - Add compatible device "boe,himax8279d10p" (Sam)
>
> Signed-off-by: Jerry Han <jerry.han.hq@gmail.com>
> Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
> Reviewed-by: Derek Basehore <dbasehore@chromium.org>
> Cc: Jitao Shi <jitao.shi@mediatek.com>
> Cc: Rock wang <rock_wang@himax.com.cn>
> ---
>  MAINTAINERS                                  |    6 +
>  drivers/gpu/drm/panel/Kconfig                |   11 +
>  drivers/gpu/drm/panel/Makefile               |    1 +
>  drivers/gpu/drm/panel/panel-boe-himax8279d.c | 1050 ++++++++++++++++++
>  4 files changed, 1068 insertions(+)
>  create mode 100644 drivers/gpu/drm/panel/panel-boe-himax8279d.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index f8e63bcc4c1c..267468ca72bb 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -4816,6 +4816,12 @@ T:       git git://
> anongit.freedesktop.org/drm/drm-misc
>  S:     Maintained
>  F:     drivers/gpu/drm/bochs/
>
> +DRM DRIVER FOR BOE HIMAX8279D PANELS
> +M:     Jerry Han <hanxu5@huaqin.corp-partner.google.com>
> +S:     Maintained
> +F:     drivers/gpu/drm/panel/panel-boe-himax8279d.c
> +F:     Documentation/devicetree/bindings/display/panel/boe,himax8279d.txt
> +
>  DRM DRIVER FOR FARADAY TVE200 TV ENCODER
>  M:     Linus Walleij <linus.walleij@linaro.org>
>  T:     git git://anongit.freedesktop.org/drm/drm-misc
> diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
> index f53f817356db..fe2f87cc6627 100644
> --- a/drivers/gpu/drm/panel/Kconfig
> +++ b/drivers/gpu/drm/panel/Kconfig
> @@ -17,6 +17,17 @@ config DRM_PANEL_ARM_VERSATILE
>           reference designs. The panel is detected using special registers
>           in the Versatile family syscon registers.
>
> +config DRM_PANEL_BOE_HIMAX8279D
> +       tristate "Boe Himax8279d panel"
> +       depends on OF
> +       depends on DRM_MIPI_DSI
> +       depends on BACKLIGHT_CLASS_DEVICE
> +       help
> +         Say Y here if you want to enable support for Boe Himax8279d
> +         TFT-LCD modules. The panel has a 1200x1920 resolution and uses
> +         24 bit RGB per pixel. It provides a MIPI DSI interface to
> +         the host and has a built-in LED backlight.
> +
>  config DRM_PANEL_LVDS
>         tristate "Generic LVDS panel driver"
>         depends on OF
> diff --git a/drivers/gpu/drm/panel/Makefile
> b/drivers/gpu/drm/panel/Makefile
> index 7834947a53b0..c4814b6f069e 100644
> --- a/drivers/gpu/drm/panel/Makefile
> +++ b/drivers/gpu/drm/panel/Makefile
> @@ -1,5 +1,6 @@
>  # SPDX-License-Identifier: GPL-2.0
>  obj-$(CONFIG_DRM_PANEL_ARM_VERSATILE) += panel-arm-versatile.o
> +obj-$(CONFIG_DRM_PANEL_BOE_HIMAX8279D) += panel-boe-himax8279d.o
>  obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o
>  obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
>  obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o
> diff --git a/drivers/gpu/drm/panel/panel-boe-himax8279d.c
> b/drivers/gpu/drm/panel/panel-boe-himax8279d.c
> new file mode 100644
> index 000000000000..9c8ece4fa30a
> --- /dev/null
> +++ b/drivers/gpu/drm/panel/panel-boe-himax8279d.c
> @@ -0,0 +1,1050 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2019, Huaqin Telecom Technology Co., Ltd
> + *
> + * Author: Jerry Han <jerry.han.hq@gmail.com>
> + *
> + */
> +
> +#include <linux/backlight.h>
> +#include <linux/delay.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +
> +#include <linux/gpio/consumer.h>
> +#include <linux/regulator/consumer.h>
> +
> +#include <drm/drm_device.h>
> +#include <drm/drm_mipi_dsi.h>
> +#include <drm/drm_modes.h>
> +#include <drm/drm_panel.h>
> +#include <drm/drm_print.h>
> +
> +#include <video/mipi_display.h>
> +
> +struct panel_cmd {
> +       size_t len;
> +       const char *data;
> +};
> +
> +#define _INIT_CMD(...) { \
> +       .len = sizeof((char[]){__VA_ARGS__}), \
> +       .data = (char[]){__VA_ARGS__} }
> +
> +struct panel_desc {
> +       const struct drm_display_mode *display_mode;
> +       unsigned int bpc;
> +       unsigned int width_mm;
> +       unsigned int height_mm;
> +
> +       unsigned int delay_t1;
> +       unsigned int reset_delay_t2;
> +       unsigned int reset_delay_t3;
> +       unsigned int reset_delay_t4;
> +       unsigned int reset_delay_t5;
> +
> +       unsigned long mode_flags;
> +       enum mipi_dsi_pixel_format format;
> +       unsigned int lanes;
> +       const struct panel_cmd *on_cmds;
> +       const struct panel_cmd *off_cmds;
> +};
> +
> +struct panel_info {
> +       struct drm_panel base;
> +       struct mipi_dsi_device *link;
> +       const struct panel_desc *desc;
> +
> +       struct backlight_device *backlight;
> +       struct gpio_desc *enable_gpio;
> +       struct gpio_desc *pp33_gpio;
> +       struct gpio_desc *pp18_gpio;
> +
> +       bool prepared;
> +       bool enabled;
> +};
> +
> +static inline struct panel_info *to_panel_info(struct drm_panel *panel)
> +{
> +       return container_of(panel, struct panel_info, base);
> +}
> +
> +static void set_gpios(struct panel_info *pinfo, int enable)
> +{
> +       gpiod_set_value(pinfo->enable_gpio, enable);
> +       gpiod_set_value(pinfo->pp33_gpio, enable);
> +       gpiod_set_value(pinfo->pp18_gpio, enable);
> +}
> +
> +static int send_mipi_cmds(struct drm_panel *panel, const struct panel_cmd
> *cmds)
> +{
> +       struct panel_info *pinfo = to_panel_info(panel);
> +       unsigned int i = 0;
> +       int err;
> +
> +       if (!cmds)
> +               return -EFAULT;
> +
> +       for (i = 0; cmds[i].len != 0; i++) {
> +               const struct panel_cmd *cmd = &cmds[i];
> +
> +               if (cmd->len == 2)
> +                       err = mipi_dsi_dcs_write(pinfo->link,
> +                                                   cmd->data[1], NULL, 0);
> +               else
> +                       err = mipi_dsi_dcs_write(pinfo->link,
> +                                                   cmd->data[1],
> cmd->data + 2,
> +                                                   cmd->len - 2);
> +
> +               if (err < 0)
> +                       return err;
> +
> +               usleep_range((cmd->data[0]) * 1000,
> +                           (1 + cmd->data[0]) * 1000);
> +       }
> +
> +       return 0;
> +}
> +
> +static int boe_panel_disable(struct drm_panel *panel)
> +{
> +       struct panel_info *pinfo = to_panel_info(panel);
> +
> +       backlight_disable(pinfo->backlight);
> +
> +       pinfo->enabled = false;
> +
> +       return 0;
> +}
> +
> +static int boe_panel_unprepare(struct drm_panel *panel)
> +{
> +       struct panel_info *pinfo = to_panel_info(panel);
> +       int err;
> +
> +       if (!pinfo->prepared)
> +               return 0;
> +
> +       /* send off code */
> +       err = send_mipi_cmds(panel, pinfo->desc->off_cmds);
> +       if (err < 0) {
> +               DRM_DEV_ERROR(panel->dev,
> +                               "failed to send DCS Off Code: %d\n", err);
> +               goto poweroff;
> +       }
> +
> +       set_gpios(pinfo, 0);
> +
> +       pinfo->prepared = false;
> +
> +       return 0;
> +
> +poweroff:
> +       set_gpios(pinfo, 0);
> +       return err;
> +}
> +
> +static int boe_panel_prepare(struct drm_panel *panel)
> +{
> +       struct panel_info *pinfo = to_panel_info(panel);
> +       const struct panel_desc *desc = pinfo->desc;
> +       int err;
> +
> +       if (pinfo->prepared)
> +               return 0;
> +
> +       gpiod_set_value(pinfo->pp18_gpio, 1);
> +       /* T1 (> 5ms) */
> +       usleep_range(desc->delay_t1, 1000 + desc->delay_t1);
> +       gpiod_set_value(pinfo->pp33_gpio, 1);
> +
> +       /* reset sequence */
> +       usleep_range(desc->reset_delay_t2, 1000 + desc->reset_delay_t2);
> +
> +       gpiod_set_value(pinfo->enable_gpio, 1);
> +       usleep_range(desc->reset_delay_t3, 1000 + desc->reset_delay_t3);
> +       gpiod_set_value(pinfo->enable_gpio, 0);
> +
> +       usleep_range(desc->reset_delay_t4, 1000 + desc->reset_delay_t4);
> +       gpiod_set_value(pinfo->enable_gpio, 1);
> +
> +       usleep_range(desc->reset_delay_t5, 1000 + desc->reset_delay_t5);
> +
> +       /* send init code */
> +       err = send_mipi_cmds(panel, pinfo->desc->on_cmds);
> +       if (err < 0) {
> +               DRM_DEV_ERROR(panel->dev,
> +                               "failed to send DCS Init Code: %d\n", err);
> +               goto poweroff;
> +       }
> +
> +       pinfo->prepared = true;
> +
> +       return 0;
> +
> +poweroff:
> +       set_gpios(pinfo, 0);
> +       return err;
> +}
> +
> +static int boe_panel_enable(struct drm_panel *panel)
> +{
> +       struct panel_info *pinfo = to_panel_info(panel);
> +       int ret;
> +
> +       if (pinfo->enabled)
> +               return 0;
> +
> +       ret = backlight_enable(pinfo->backlight);
> +       if (ret) {
> +               DRM_DEV_ERROR(panel->drm->dev,
> +                               "Failed to enable backlight %d\n", ret);
> +               return ret;
> +       }
> +
> +       pinfo->enabled = true;
> +
> +       return 0;
> +}
> +
> +static int boe_panel_get_modes(struct drm_panel *panel)
> +{
> +       struct panel_info *pinfo = to_panel_info(panel);
> +       const struct drm_display_mode *m = pinfo->desc->display_mode;
> +       struct drm_display_mode *mode;
> +
> +       mode = drm_mode_duplicate(panel->drm, m);
> +       if (!mode) {
> +               DRM_DEV_ERROR(panel->drm->dev, "failed to add mode %ux%u@
> %u\n",
> +                               m->hdisplay, m->vdisplay, m->vrefresh);
> +               return -ENOMEM;
> +       }
> +
> +       drm_mode_set_name(mode);
> +
> +       drm_mode_probed_add(panel->connector, mode);
> +
> +       panel->connector->display_info.width_mm = pinfo->desc->width_mm;
> +       panel->connector->display_info.height_mm = pinfo->desc->height_mm;
> +       panel->connector->display_info.bpc = pinfo->desc->bpc;
> +
> +       return 1;
> +}
> +
> +static const struct drm_panel_funcs panel_funcs = {
> +       .disable = boe_panel_disable,
> +       .unprepare = boe_panel_unprepare,
> +       .prepare = boe_panel_prepare,
> +       .enable = boe_panel_enable,
> +       .get_modes = boe_panel_get_modes,
> +};
> +
> +static const struct drm_display_mode default_display_mode = {
> +       .clock = 159420,
> +       .hdisplay = 1200,
> +       .hsync_start = 1200 + 80,
> +       .hsync_end = 1200 + 80 + 60,
> +       .htotal = 1200 + 80 + 60 + 24,
> +       .vdisplay = 1920,
> +       .vsync_start = 1920 + 10,
> +       .vsync_end = 1920 + 10 + 14,
> +       .vtotal = 1920 + 10 + 14 + 4,
> +       .vrefresh = 60,
> +};
> +
> +static const struct panel_cmd default_off_cmds[] = {
> +       _INIT_CMD(0x00, 0x28),
> +       _INIT_CMD(0x01, 0x10),
> +
> +       {},
> +};
> +
> +/* 8 inch */
> +static const struct panel_cmd boe_himax8279d8p_on_cmds[] = {
> +       _INIT_CMD(0x22, 0x10),
> +       _INIT_CMD(0x00, 0xB0, 0x05),
> +       _INIT_CMD(0x00, 0xB1, 0xE5),
> +       _INIT_CMD(0x00, 0xB3, 0x52),
> +       _INIT_CMD(0x00, 0xB0, 0x00),
> +       _INIT_CMD(0x00, 0xB3, 0x88),
> +       _INIT_CMD(0x00, 0xB0, 0x04),
> +       _INIT_CMD(0x00, 0xB8, 0x00),
> +       _INIT_CMD(0x00, 0xB0, 0x00),
> +       _INIT_CMD(0x00, 0xB2, 0x50),
> +       _INIT_CMD(0x00, 0xB6, 0x03),
> +       _INIT_CMD(0x00, 0xBA, 0x8B),
> +       _INIT_CMD(0x00, 0xBF, 0x15),
> +       _INIT_CMD(0x00, 0xC0, 0x0F),
> +       _INIT_CMD(0x00, 0xC2, 0x0C),
> +       _INIT_CMD(0x00, 0xC3, 0x02),
> +       _INIT_CMD(0x00, 0xC4, 0x0C),
> +       _INIT_CMD(0x00, 0xC5, 0x02),
> +       _INIT_CMD(0x00, 0xB0, 0x01),
> +       _INIT_CMD(0x00, 0xE0, 0x26),
> +       _INIT_CMD(0x00, 0xE1, 0x26),
> +       _INIT_CMD(0x00, 0xDC, 0x00),
> +       _INIT_CMD(0x00, 0xDD, 0x00),
> +       _INIT_CMD(0x00, 0xCC, 0x26),
> +       _INIT_CMD(0x00, 0xCD, 0x26),
> +       _INIT_CMD(0x00, 0xC8, 0x00),
> +       _INIT_CMD(0x00, 0xC9, 0x00),
> +       _INIT_CMD(0x00, 0xD2, 0x04),
> +       _INIT_CMD(0x00, 0xD3, 0x04),
> +       _INIT_CMD(0x00, 0xE6, 0x03),
> +       _INIT_CMD(0x00, 0xE7, 0x03),
> +       _INIT_CMD(0x00, 0xC4, 0x08),
> +       _INIT_CMD(0x00, 0xC5, 0x08),
> +       _INIT_CMD(0x00, 0xD8, 0x07),
> +       _INIT_CMD(0x00, 0xD9, 0x07),
> +       _INIT_CMD(0x00, 0xC2, 0x06),
> +       _INIT_CMD(0x00, 0xC3, 0x06),
> +       _INIT_CMD(0x00, 0xD6, 0x05),
> +       _INIT_CMD(0x00, 0xD7, 0x05),
> +       _INIT_CMD(0x00, 0xC0, 0x0C),
> +       _INIT_CMD(0x00, 0xC1, 0x0C),
> +       _INIT_CMD(0x00, 0xD4, 0x0B),
> +       _INIT_CMD(0x00, 0xD5, 0x0B),
> +       _INIT_CMD(0x00, 0xCA, 0x0A),
> +       _INIT_CMD(0x00, 0xCB, 0x0A),
> +       _INIT_CMD(0x00, 0xDE, 0x09),
> +       _INIT_CMD(0x00, 0xDF, 0x09),
> +       _INIT_CMD(0x00, 0xC6, 0x26),
> +       _INIT_CMD(0x00, 0xC7, 0x26),
> +       _INIT_CMD(0x00, 0xCE, 0x00),
> +       _INIT_CMD(0x00, 0xCF, 0x00),
> +       _INIT_CMD(0x00, 0xDA, 0x26),
> +       _INIT_CMD(0x00, 0xDB, 0x26),
> +       _INIT_CMD(0x00, 0xE2, 0x00),
> +       _INIT_CMD(0x00, 0xE3, 0x00),
> +       _INIT_CMD(0x00, 0xB0, 0x02),
> +       _INIT_CMD(0x00, 0xC0, 0x00),
> +       _INIT_CMD(0x00, 0xC1, 0x07),
> +       _INIT_CMD(0x00, 0xC2, 0x0D),
> +       _INIT_CMD(0x00, 0xC3, 0x18),
> +       _INIT_CMD(0x00, 0xC4, 0x27),
> +       _INIT_CMD(0x00, 0xC5, 0x28),
> +       _INIT_CMD(0x00, 0xC6, 0x30),
> +       _INIT_CMD(0x00, 0xC7, 0x2E),
> +       _INIT_CMD(0x00, 0xC8, 0x2F),
> +       _INIT_CMD(0x00, 0xC9, 0x1A),
> +       _INIT_CMD(0x00, 0xCA, 0x20),
> +       _INIT_CMD(0x00, 0xCB, 0x29),
> +       _INIT_CMD(0x00, 0xCC, 0x26),
> +       _INIT_CMD(0x00, 0xCD, 0x32),
> +       _INIT_CMD(0x00, 0xCE, 0x33),
> +       _INIT_CMD(0x00, 0xCF, 0x31),
> +       _INIT_CMD(0x00, 0xD0, 0x06),
> +       _INIT_CMD(0x00, 0xD2, 0x00),
> +       _INIT_CMD(0x00, 0xD3, 0x07),
> +       _INIT_CMD(0x00, 0xD4, 0x12),
> +       _INIT_CMD(0x00, 0xD5, 0x26),
> +       _INIT_CMD(0x00, 0xD6, 0x3D),
> +       _INIT_CMD(0x00, 0xD7, 0x3F),
> +       _INIT_CMD(0x00, 0xD8, 0x3F),
> +       _INIT_CMD(0x00, 0xD9, 0x3F),
> +       _INIT_CMD(0x00, 0xDA, 0x3F),
> +       _INIT_CMD(0x00, 0xDB, 0x3F),
> +       _INIT_CMD(0x00, 0xDC, 0x3F),
> +       _INIT_CMD(0x00, 0xDD, 0x3F),
> +       _INIT_CMD(0x00, 0xDE, 0x3F),
> +       _INIT_CMD(0x00, 0xDF, 0x3A),
> +       _INIT_CMD(0x00, 0xE0, 0x37),
> +       _INIT_CMD(0x00, 0xE1, 0x35),
> +       _INIT_CMD(0x00, 0xE2, 0x07),
> +       _INIT_CMD(0x00, 0xB0, 0x03),
> +       _INIT_CMD(0x00, 0xC8, 0x0B),
> +       _INIT_CMD(0x00, 0xC9, 0x07),
> +       _INIT_CMD(0x00, 0xC3, 0x00),
> +       _INIT_CMD(0x00, 0xE7, 0x00),
> +       _INIT_CMD(0x00, 0xC5, 0x2A),
> +       _INIT_CMD(0x00, 0xDE, 0x2A),
> +       _INIT_CMD(0x00, 0xCA, 0x43),
> +       _INIT_CMD(0x00, 0xC9, 0x07),
> +       _INIT_CMD(0x00, 0xE4, 0xC0),
> +       _INIT_CMD(0x00, 0xE5, 0x0D),
> +       _INIT_CMD(0x00, 0xCB, 0x00),
> +       _INIT_CMD(0x00, 0xB0, 0x06),
> +       _INIT_CMD(0x00, 0xB8, 0xA5),
> +       _INIT_CMD(0x00, 0xC0, 0xA5),
> +       _INIT_CMD(0x00, 0xC7, 0x0F),
> +       _INIT_CMD(0x00, 0xD5, 0x32),
> +       _INIT_CMD(0x00, 0xB8, 0x00),
> +       _INIT_CMD(0x00, 0xC0, 0x00),
> +       _INIT_CMD(0x00, 0xBC, 0x00),
> +       _INIT_CMD(0x00, 0xB0, 0x07),
> +       _INIT_CMD(0x00, 0xB1, 0x00),
> +       _INIT_CMD(0x00, 0xB2, 0x09),
> +       _INIT_CMD(0x00, 0xB3, 0x19),
> +       _INIT_CMD(0x00, 0xB4, 0x2F),
> +       _INIT_CMD(0x00, 0xB5, 0x44),
> +       _INIT_CMD(0x00, 0xB6, 0x52),
> +       _INIT_CMD(0x00, 0xB7, 0x6A),
> +       _INIT_CMD(0x00, 0xB8, 0x8A),
> +       _INIT_CMD(0x00, 0xB9, 0xCA),
> +       _INIT_CMD(0x00, 0xBA, 0x0C),
> +       _INIT_CMD(0x05, 0xBB, 0x87),
> +       _INIT_CMD(0x00, 0xBC, 0x06),
> +       _INIT_CMD(0x00, 0xBD, 0x0A),
> +       _INIT_CMD(0x00, 0xBE, 0x9B),
> +       _INIT_CMD(0x00, 0xBF, 0x0C),
> +       _INIT_CMD(0x00, 0xC0, 0x3D),
> +       _INIT_CMD(0x00, 0xC1, 0x71),
> +       _INIT_CMD(0x00, 0xC2, 0x90),
> +       _INIT_CMD(0x00, 0xC3, 0xA0),
> +       _INIT_CMD(0x00, 0xC4, 0xA8),
> +       _INIT_CMD(0x00, 0xC5, 0xB1),
> +       _INIT_CMD(0x00, 0xC6, 0xBB),
> +       _INIT_CMD(0x00, 0xC7, 0xC0),
> +       _INIT_CMD(0x00, 0xC8, 0xC4),
> +       _INIT_CMD(0x00, 0xC9, 0x00),
> +       _INIT_CMD(0x00, 0xCA, 0x00),
> +       _INIT_CMD(0x00, 0xCB, 0x16),
> +       _INIT_CMD(0x00, 0xCC, 0xAF),
> +       _INIT_CMD(0x00, 0xCD, 0xFF),
> +       _INIT_CMD(0x00, 0xCE, 0xFF),
> +       _INIT_CMD(0x00, 0xB0, 0x08),
> +       _INIT_CMD(0x00, 0xB1, 0x04),
> +       _INIT_CMD(0x00, 0xB2, 0x08),
> +       _INIT_CMD(0x00, 0xB3, 0x19),
> +       _INIT_CMD(0x00, 0xB4, 0x31),
> +       _INIT_CMD(0x00, 0xB5, 0x46),
> +       _INIT_CMD(0x00, 0xB6, 0x55),
> +       _INIT_CMD(0x00, 0xB7, 0x6E),
> +       _INIT_CMD(0x00, 0xB8, 0x92),
> +       _INIT_CMD(0x00, 0xB9, 0xD4),
> +       _INIT_CMD(0x00, 0xBA, 0x1B),
> +       _INIT_CMD(0x05, 0xBB, 0x9B),
> +       _INIT_CMD(0x00, 0xBC, 0x28),
> +       _INIT_CMD(0x00, 0xBD, 0x2D),
> +       _INIT_CMD(0x00, 0xBE, 0xC3),
> +       _INIT_CMD(0x00, 0xBF, 0x2F),
> +       _INIT_CMD(0x00, 0xC0, 0x62),
> +       _INIT_CMD(0x00, 0xC1, 0x99),
> +       _INIT_CMD(0x00, 0xC2, 0xAB),
> +       _INIT_CMD(0x00, 0xC3, 0xBF),
> +       _INIT_CMD(0x00, 0xC4, 0xCF),
> +       _INIT_CMD(0x00, 0xC5, 0xDF),
> +       _INIT_CMD(0x00, 0xC6, 0xF0),
> +       _INIT_CMD(0x00, 0xC7, 0xF9),
> +       _INIT_CMD(0x00, 0xC8, 0xFC),
> +       _INIT_CMD(0x00, 0xC9, 0x00),
> +       _INIT_CMD(0x00, 0xCA, 0x00),
> +       _INIT_CMD(0x00, 0xCB, 0x16),
> +       _INIT_CMD(0x00, 0xCC, 0xAF),
> +       _INIT_CMD(0x00, 0xCD, 0xFF),
> +       _INIT_CMD(0x00, 0xCE, 0xFF),
> +       _INIT_CMD(0x00, 0xB0, 0x09),
> +       _INIT_CMD(0x00, 0xB1, 0x04),
> +       _INIT_CMD(0x00, 0xB2, 0x05),
> +       _INIT_CMD(0x00, 0xB3, 0x17),
> +       _INIT_CMD(0x00, 0xB4, 0x2E),
> +       _INIT_CMD(0x00, 0xB5, 0x42),
> +       _INIT_CMD(0x00, 0xB6, 0x51),
> +       _INIT_CMD(0x00, 0xB7, 0x69),
> +       _INIT_CMD(0x00, 0xB8, 0x88),
> +       _INIT_CMD(0x00, 0xB9, 0xC9),
> +       _INIT_CMD(0x00, 0xBA, 0x0C),
> +       _INIT_CMD(0x05, 0xBB, 0x86),
> +       _INIT_CMD(0x00, 0xBC, 0x03),
> +       _INIT_CMD(0x00, 0xBD, 0x08),
> +       _INIT_CMD(0x00, 0xBE, 0x95),
> +       _INIT_CMD(0x00, 0xBF, 0x05),
> +       _INIT_CMD(0x00, 0xC0, 0x35),
> +       _INIT_CMD(0x00, 0xC1, 0x62),
> +       _INIT_CMD(0x00, 0xC2, 0x81),
> +       _INIT_CMD(0x00, 0xC3, 0x96),
> +       _INIT_CMD(0x00, 0xC4, 0x9E),
> +       _INIT_CMD(0x00, 0xC5, 0xA5),
> +       _INIT_CMD(0x00, 0xC6, 0xAD),
> +       _INIT_CMD(0x00, 0xC7, 0xB1),
> +       _INIT_CMD(0x00, 0xC8, 0xB4),
> +       _INIT_CMD(0x00, 0xC9, 0x00),
> +       _INIT_CMD(0x00, 0xCA, 0x00),
> +       _INIT_CMD(0x00, 0xCB, 0x16),
> +       _INIT_CMD(0x00, 0xCC, 0xAF),
> +       _INIT_CMD(0x00, 0xCD, 0xFF),
> +       _INIT_CMD(0x00, 0xCE, 0xFF),
> +       _INIT_CMD(0x00, 0xB0, 0x0A),
> +       _INIT_CMD(0x00, 0xB1, 0x00),
> +       _INIT_CMD(0x00, 0xB2, 0x09),
> +       _INIT_CMD(0x00, 0xB3, 0x19),
> +       _INIT_CMD(0x00, 0xB4, 0x2F),
> +       _INIT_CMD(0x00, 0xB5, 0x44),
> +       _INIT_CMD(0x00, 0xB6, 0x52),
> +       _INIT_CMD(0x00, 0xB7, 0x6A),
> +       _INIT_CMD(0x00, 0xB8, 0x8A),
> +       _INIT_CMD(0x00, 0xB9, 0xCA),
> +       _INIT_CMD(0x00, 0xBA, 0x0C),
> +       _INIT_CMD(0x05, 0xBB, 0x87),
> +       _INIT_CMD(0x00, 0xBC, 0x06),
> +       _INIT_CMD(0x00, 0xBD, 0x0A),
> +       _INIT_CMD(0x00, 0xBE, 0x9B),
> +       _INIT_CMD(0x00, 0xBF, 0x0C),
> +       _INIT_CMD(0x00, 0xC0, 0x3D),
> +       _INIT_CMD(0x00, 0xC1, 0x71),
> +       _INIT_CMD(0x00, 0xC2, 0x90),
> +       _INIT_CMD(0x00, 0xC3, 0xA0),
> +       _INIT_CMD(0x00, 0xC4, 0xA8),
> +       _INIT_CMD(0x00, 0xC5, 0xB1),
> +       _INIT_CMD(0x00, 0xC6, 0xBB),
> +       _INIT_CMD(0x00, 0xC7, 0xC0),
> +       _INIT_CMD(0x00, 0xC8, 0xC4),
> +       _INIT_CMD(0x00, 0xC9, 0x00),
> +       _INIT_CMD(0x00, 0xCA, 0x00),
> +       _INIT_CMD(0x00, 0xCB, 0x16),
> +       _INIT_CMD(0x00, 0xCC, 0xAF),
> +       _INIT_CMD(0x00, 0xCD, 0xFF),
> +       _INIT_CMD(0x00, 0xCE, 0xFF),
> +       _INIT_CMD(0x00, 0xB0, 0x0B),
> +       _INIT_CMD(0x00, 0xB1, 0x04),
> +       _INIT_CMD(0x00, 0xB2, 0x08),
> +       _INIT_CMD(0x00, 0xB3, 0x19),
> +       _INIT_CMD(0x00, 0xB4, 0x31),
> +       _INIT_CMD(0x00, 0xB5, 0x46),
> +       _INIT_CMD(0x00, 0xB6, 0x55),
> +       _INIT_CMD(0x00, 0xB7, 0x6E),
> +       _INIT_CMD(0x00, 0xB8, 0x92),
> +       _INIT_CMD(0x00, 0xB9, 0xD4),
> +       _INIT_CMD(0x00, 0xBA, 0x1B),
> +       _INIT_CMD(0x05, 0xBB, 0x9B),
> +       _INIT_CMD(0x00, 0xBC, 0x28),
> +       _INIT_CMD(0x00, 0xBD, 0x2D),
> +       _INIT_CMD(0x00, 0xBE, 0xC3),
> +       _INIT_CMD(0x00, 0xBF, 0x2F),
> +       _INIT_CMD(0x00, 0xC0, 0x62),
> +       _INIT_CMD(0x00, 0xC1, 0x99),
> +       _INIT_CMD(0x00, 0xC2, 0xAB),
> +       _INIT_CMD(0x00, 0xC3, 0xBF),
> +       _INIT_CMD(0x00, 0xC4, 0xCF),
> +       _INIT_CMD(0x00, 0xC5, 0xDF),
> +       _INIT_CMD(0x00, 0xC6, 0xF0),
> +       _INIT_CMD(0x00, 0xC7, 0xF9),
> +       _INIT_CMD(0x00, 0xC8, 0xFC),
> +       _INIT_CMD(0x00, 0xC9, 0x00),
> +       _INIT_CMD(0x00, 0xCA, 0x00),
> +       _INIT_CMD(0x00, 0xCB, 0x16),
> +       _INIT_CMD(0x00, 0xCC, 0xAF),
> +       _INIT_CMD(0x00, 0xCD, 0xFF),
> +       _INIT_CMD(0x00, 0xCE, 0xFF),
> +       _INIT_CMD(0x00, 0xB0, 0x0C),
> +       _INIT_CMD(0x00, 0xB1, 0x04),
> +       _INIT_CMD(0x00, 0xB2, 0x05),
> +       _INIT_CMD(0x00, 0xB3, 0x17),
> +       _INIT_CMD(0x00, 0xB4, 0x2E),
> +       _INIT_CMD(0x00, 0xB5, 0x42),
> +       _INIT_CMD(0x00, 0xB6, 0x51),
> +       _INIT_CMD(0x00, 0xB7, 0x69),
> +       _INIT_CMD(0x00, 0xB8, 0x88),
> +       _INIT_CMD(0x00, 0xB9, 0xC9),
> +       _INIT_CMD(0x00, 0xBA, 0x0C),
> +       _INIT_CMD(0x05, 0xBB, 0x86),
> +       _INIT_CMD(0x00, 0xBC, 0x03),
> +       _INIT_CMD(0x00, 0xBD, 0x08),
> +       _INIT_CMD(0x00, 0xBE, 0x95),
> +       _INIT_CMD(0x00, 0xBF, 0x05),
> +       _INIT_CMD(0x00, 0xC0, 0x35),
> +       _INIT_CMD(0x00, 0xC1, 0x62),
> +       _INIT_CMD(0x00, 0xC2, 0x81),
> +       _INIT_CMD(0x00, 0xC3, 0x96),
> +       _INIT_CMD(0x00, 0xC4, 0x9E),
> +       _INIT_CMD(0x00, 0xC5, 0xA5),
> +       _INIT_CMD(0x00, 0xC6, 0xAD),
> +       _INIT_CMD(0x00, 0xC7, 0xB1),
> +       _INIT_CMD(0x00, 0xC8, 0xB4),
> +       _INIT_CMD(0x00, 0xC9, 0x00),
> +       _INIT_CMD(0x00, 0xCA, 0x00),
> +       _INIT_CMD(0x00, 0xCB, 0x16),
> +       _INIT_CMD(0x00, 0xCC, 0xAF),
> +       _INIT_CMD(0x00, 0xCD, 0xFF),
> +       _INIT_CMD(0x64, 0xCE, 0xFF),
> +       _INIT_CMD(0x00, 0xB0, 0x00),
> +       _INIT_CMD(0x00, 0xB3, 0x08),
> +       _INIT_CMD(0x00, 0xB0, 0x04),
> +       _INIT_CMD(0x0A, 0xB8, 0x68),
> +       _INIT_CMD(0x78, 0x11),
> +       _INIT_CMD(0x14, 0x29),
> +
> +       {},
> +};
> +
> +static const struct panel_desc boe_himax8279d8p_panel_desc = {
> +       .display_mode = &default_display_mode,
> +       .bpc = 8,
> +       .width_mm = 107,
> +       .height_mm = 172,
> +       .delay_t1 = 5000,
> +       .reset_delay_t2 = 14000,
> +       .reset_delay_t3 = 1000,
> +       .reset_delay_t4 = 1000,
> +       .reset_delay_t5 = 5000,
> +       .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE
> |
> +                       MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,
> +       .format = MIPI_DSI_FMT_RGB888,
> +       .lanes = 4,
> +       .on_cmds = boe_himax8279d8p_on_cmds,
> +       .off_cmds = default_off_cmds,
> +};
> +
> +/* 10 inch */
> +static const struct panel_cmd boe_himax8279d10p_on_cmds[] = {
> +       _INIT_CMD(0x00, 0xB0, 0x05),
> +       _INIT_CMD(0x00, 0xB1, 0xE5),
> +       _INIT_CMD(0x00, 0xB3, 0x52),
> +       _INIT_CMD(0x00, 0xB0, 0x00),
> +       _INIT_CMD(0x00, 0xB3, 0x88),
> +       _INIT_CMD(0x00, 0xB0, 0x04),
> +       _INIT_CMD(0x00, 0xB8, 0x00),
> +       _INIT_CMD(0x00, 0xB0, 0x00),
> +       _INIT_CMD(0x00, 0xB2, 0x50),
> +       _INIT_CMD(0x00, 0xB6, 0x03),
> +       _INIT_CMD(0x00, 0xBA, 0x8B),
> +       _INIT_CMD(0x00, 0xBF, 0x1A),
> +       _INIT_CMD(0x00, 0xC0, 0x0F),
> +       _INIT_CMD(0x00, 0xC2, 0x0C),
> +       _INIT_CMD(0x00, 0xC3, 0x02),
> +       _INIT_CMD(0x00, 0xC4, 0x0C),
> +       _INIT_CMD(0x00, 0xC5, 0x02),
> +       _INIT_CMD(0x00, 0xB0, 0x01),
> +       _INIT_CMD(0x00, 0xE0, 0x26),
> +       _INIT_CMD(0x00, 0xE1, 0x26),
> +       _INIT_CMD(0x00, 0xDC, 0x00),
> +       _INIT_CMD(0x00, 0xDD, 0x00),
> +       _INIT_CMD(0x00, 0xCC, 0x26),
> +       _INIT_CMD(0x00, 0xCD, 0x26),
> +       _INIT_CMD(0x00, 0xC8, 0x00),
> +       _INIT_CMD(0x00, 0xC9, 0x00),
> +       _INIT_CMD(0x00, 0xD2, 0x04),
> +       _INIT_CMD(0x00, 0xD3, 0x04),
> +       _INIT_CMD(0x00, 0xE6, 0x03),
> +       _INIT_CMD(0x00, 0xE7, 0x03),
> +       _INIT_CMD(0x00, 0xC4, 0x08),
> +       _INIT_CMD(0x00, 0xC5, 0x08),
> +       _INIT_CMD(0x00, 0xD8, 0x07),
> +       _INIT_CMD(0x00, 0xD9, 0x07),
> +       _INIT_CMD(0x00, 0xC2, 0x06),
> +       _INIT_CMD(0x00, 0xC3, 0x06),
> +       _INIT_CMD(0x00, 0xD6, 0x05),
> +       _INIT_CMD(0x00, 0xD7, 0x05),
> +       _INIT_CMD(0x00, 0xC0, 0x0C),
> +       _INIT_CMD(0x00, 0xC1, 0x0C),
> +       _INIT_CMD(0x00, 0xD4, 0x0B),
> +       _INIT_CMD(0x00, 0xD5, 0x0B),
> +       _INIT_CMD(0x00, 0xCA, 0x0A),
> +       _INIT_CMD(0x00, 0xCB, 0x0A),
> +       _INIT_CMD(0x00, 0xDE, 0x09),
> +       _INIT_CMD(0x00, 0xDF, 0x09),
> +       _INIT_CMD(0x00, 0xC6, 0x26),
> +       _INIT_CMD(0x00, 0xC7, 0x26),
> +       _INIT_CMD(0x00, 0xCE, 0x00),
> +       _INIT_CMD(0x00, 0xCF, 0x00),
> +       _INIT_CMD(0x00, 0xDA, 0x26),
> +       _INIT_CMD(0x00, 0xDB, 0x26),
> +       _INIT_CMD(0x00, 0xE2, 0x00),
> +       _INIT_CMD(0x00, 0xE3, 0x00),
> +       _INIT_CMD(0x00, 0xB0, 0x02),
> +       _INIT_CMD(0x00, 0xC0, 0x00),
> +       _INIT_CMD(0x00, 0xC1, 0x07),
> +       _INIT_CMD(0x00, 0xC2, 0x0D),
> +       _INIT_CMD(0x00, 0xC3, 0x18),
> +       _INIT_CMD(0x00, 0xC4, 0x27),
> +       _INIT_CMD(0x00, 0xC5, 0x28),
> +       _INIT_CMD(0x00, 0xC6, 0x30),
> +       _INIT_CMD(0x00, 0xC7, 0x2E),
> +       _INIT_CMD(0x00, 0xC8, 0x2F),
> +       _INIT_CMD(0x00, 0xC9, 0x1A),
> +       _INIT_CMD(0x00, 0xCA, 0x20),
> +       _INIT_CMD(0x00, 0xCB, 0x29),
> +       _INIT_CMD(0x00, 0xCC, 0x26),
> +       _INIT_CMD(0x00, 0xCD, 0x32),
> +       _INIT_CMD(0x00, 0xCE, 0x33),
> +       _INIT_CMD(0x00, 0xCF, 0x31),
> +       _INIT_CMD(0x00, 0xD0, 0x06),
> +       _INIT_CMD(0x00, 0xD2, 0x00),
> +       _INIT_CMD(0x00, 0xD3, 0x07),
> +       _INIT_CMD(0x00, 0xD4, 0x12),
> +       _INIT_CMD(0x00, 0xD5, 0x26),
> +       _INIT_CMD(0x00, 0xD6, 0x3D),
> +       _INIT_CMD(0x00, 0xD7, 0x3F),
> +       _INIT_CMD(0x00, 0xD8, 0x3F),
> +       _INIT_CMD(0x00, 0xD9, 0x3F),
> +       _INIT_CMD(0x00, 0xDA, 0x3F),
> +       _INIT_CMD(0x00, 0xDB, 0x3F),
> +       _INIT_CMD(0x00, 0xDC, 0x3F),
> +       _INIT_CMD(0x00, 0xDD, 0x3F),
> +       _INIT_CMD(0x00, 0xDE, 0x3F),
> +       _INIT_CMD(0x00, 0xDF, 0x3A),
> +       _INIT_CMD(0x00, 0xE0, 0x37),
> +       _INIT_CMD(0x00, 0xE1, 0x35),
> +       _INIT_CMD(0x00, 0xE2, 0x07),
> +       _INIT_CMD(0x00, 0xB0, 0x03),
> +       _INIT_CMD(0x00, 0xC8, 0x0B),
> +       _INIT_CMD(0x00, 0xC9, 0x07),
> +       _INIT_CMD(0x00, 0xC3, 0x00),
> +       _INIT_CMD(0x00, 0xE7, 0x00),
> +       _INIT_CMD(0x00, 0xC5, 0x2A),
> +       _INIT_CMD(0x00, 0xDE, 0x2A),
> +       _INIT_CMD(0x00, 0xCA, 0x43),
> +       _INIT_CMD(0x00, 0xC9, 0x07),
> +       _INIT_CMD(0x00, 0xE4, 0xC0),
> +       _INIT_CMD(0x00, 0xE5, 0x0D),
> +       _INIT_CMD(0x00, 0xCB, 0x00),
> +       _INIT_CMD(0x00, 0xB0, 0x06),
> +       _INIT_CMD(0x00, 0xB8, 0xA5),
> +       _INIT_CMD(0x00, 0xC0, 0xA5),
> +       _INIT_CMD(0x00, 0xC7, 0x0F),
> +       _INIT_CMD(0x00, 0xD5, 0x32),
> +       _INIT_CMD(0x00, 0xB8, 0x00),
> +       _INIT_CMD(0x00, 0xC0, 0x00),
> +       _INIT_CMD(0x00, 0xBC, 0x00),
> +       _INIT_CMD(0x00, 0xB0, 0x07),
> +       _INIT_CMD(0x00, 0xB1, 0x00),
> +       _INIT_CMD(0x00, 0xB2, 0x09),
> +       _INIT_CMD(0x00, 0xB3, 0x19),
> +       _INIT_CMD(0x00, 0xB4, 0x2F),
> +       _INIT_CMD(0x00, 0xB5, 0x44),
> +       _INIT_CMD(0x00, 0xB6, 0x52),
> +       _INIT_CMD(0x00, 0xB7, 0x6A),
> +       _INIT_CMD(0x00, 0xB8, 0x8A),
> +       _INIT_CMD(0x00, 0xB9, 0xCA),
> +       _INIT_CMD(0x00, 0xBA, 0x0C),
> +       _INIT_CMD(0x00, 0xBB, 0x87),
> +       _INIT_CMD(0x00, 0xBC, 0x06),
> +       _INIT_CMD(0x00, 0xBD, 0x0A),
> +       _INIT_CMD(0x00, 0xBE, 0x9B),
> +       _INIT_CMD(0x00, 0xBF, 0x0C),
> +       _INIT_CMD(0x00, 0xC0, 0x3D),
> +       _INIT_CMD(0x00, 0xC1, 0x71),
> +       _INIT_CMD(0x00, 0xC2, 0x90),
> +       _INIT_CMD(0x00, 0xC3, 0xA0),
> +       _INIT_CMD(0x00, 0xC4, 0xA8),
> +       _INIT_CMD(0x00, 0xC5, 0xB1),
> +       _INIT_CMD(0x00, 0xC6, 0xBB),
> +       _INIT_CMD(0x00, 0xC7, 0xC0),
> +       _INIT_CMD(0x00, 0xC8, 0xC4),
> +       _INIT_CMD(0x00, 0xC9, 0x00),
> +       _INIT_CMD(0x00, 0xCA, 0x00),
> +       _INIT_CMD(0x00, 0xCB, 0x16),
> +       _INIT_CMD(0x00, 0xCC, 0xAF),
> +       _INIT_CMD(0x00, 0xCD, 0xFF),
> +       _INIT_CMD(0x00, 0xCE, 0xFF),
> +       _INIT_CMD(0x00, 0xB0, 0x08),
> +       _INIT_CMD(0x00, 0xB1, 0x04),
> +       _INIT_CMD(0x00, 0xB2, 0x08),
> +       _INIT_CMD(0x00, 0xB3, 0x19),
> +       _INIT_CMD(0x00, 0xB4, 0x31),
> +       _INIT_CMD(0x00, 0xB5, 0x46),
> +       _INIT_CMD(0x00, 0xB6, 0x55),
> +       _INIT_CMD(0x00, 0xB7, 0x6E),
> +       _INIT_CMD(0x00, 0xB8, 0x92),
> +       _INIT_CMD(0x00, 0xB9, 0xD4),
> +       _INIT_CMD(0x00, 0xBA, 0x1B),
> +       _INIT_CMD(0x00, 0xBB, 0x9B),
> +       _INIT_CMD(0x00, 0xBC, 0x28),
> +       _INIT_CMD(0x00, 0xBD, 0x2D),
> +       _INIT_CMD(0x00, 0xBE, 0xC3),
> +       _INIT_CMD(0x00, 0xBF, 0x2F),
> +       _INIT_CMD(0x00, 0xC0, 0x62),
> +       _INIT_CMD(0x00, 0xC1, 0x99),
> +       _INIT_CMD(0x00, 0xC2, 0xAB),
> +       _INIT_CMD(0x00, 0xC3, 0xBF),
> +       _INIT_CMD(0x00, 0xC4, 0xCF),
> +       _INIT_CMD(0x00, 0xC5, 0xDF),
> +       _INIT_CMD(0x00, 0xC6, 0xF0),
> +       _INIT_CMD(0x00, 0xC7, 0xF9),
> +       _INIT_CMD(0x00, 0xC8, 0xFC),
> +       _INIT_CMD(0x00, 0xC9, 0x00),
> +       _INIT_CMD(0x00, 0xCA, 0x00),
> +       _INIT_CMD(0x00, 0xCB, 0x16),
> +       _INIT_CMD(0x00, 0xCC, 0xAF),
> +       _INIT_CMD(0x00, 0xCD, 0xFF),
> +       _INIT_CMD(0x00, 0xCE, 0xFF),
> +       _INIT_CMD(0x00, 0xB0, 0x09),
> +       _INIT_CMD(0x00, 0xB1, 0x04),
> +       _INIT_CMD(0x00, 0xB2, 0x05),
> +       _INIT_CMD(0x00, 0xB3, 0x17),
> +       _INIT_CMD(0x00, 0xB4, 0x2E),
> +       _INIT_CMD(0x00, 0xB5, 0x42),
> +       _INIT_CMD(0x00, 0xB6, 0x51),
> +       _INIT_CMD(0x00, 0xB7, 0x69),
> +       _INIT_CMD(0x00, 0xB8, 0x88),
> +       _INIT_CMD(0x00, 0xB9, 0xC9),
> +       _INIT_CMD(0x00, 0xBA, 0x0C),
> +       _INIT_CMD(0x00, 0xBB, 0x86),
> +       _INIT_CMD(0x00, 0xBC, 0x03),
> +       _INIT_CMD(0x00, 0xBD, 0x08),
> +       _INIT_CMD(0x00, 0xBE, 0x95),
> +       _INIT_CMD(0x00, 0xBF, 0x05),
> +       _INIT_CMD(0x00, 0xC0, 0x35),
> +       _INIT_CMD(0x00, 0xC1, 0x62),
> +       _INIT_CMD(0x00, 0xC2, 0x81),
> +       _INIT_CMD(0x00, 0xC3, 0x96),
> +       _INIT_CMD(0x00, 0xC4, 0x9E),
> +       _INIT_CMD(0x00, 0xC5, 0xA5),
> +       _INIT_CMD(0x00, 0xC6, 0xAD),
> +       _INIT_CMD(0x00, 0xC7, 0xB1),
> +       _INIT_CMD(0x00, 0xC8, 0xB4),
> +       _INIT_CMD(0x00, 0xC9, 0x00),
> +       _INIT_CMD(0x00, 0xCA, 0x00),
> +       _INIT_CMD(0x00, 0xCB, 0x16),
> +       _INIT_CMD(0x00, 0xCC, 0xAF),
> +       _INIT_CMD(0x00, 0xCD, 0xFF),
> +       _INIT_CMD(0x00, 0xCE, 0xFF),
> +       _INIT_CMD(0x00, 0xB0, 0x0A),
> +       _INIT_CMD(0x00, 0xB1, 0x00),
> +       _INIT_CMD(0x00, 0xB2, 0x09),
> +       _INIT_CMD(0x00, 0xB3, 0x19),
> +       _INIT_CMD(0x00, 0xB4, 0x2F),
> +       _INIT_CMD(0x00, 0xB5, 0x44),
> +       _INIT_CMD(0x00, 0xB6, 0x52),
> +       _INIT_CMD(0x00, 0xB7, 0x6A),
> +       _INIT_CMD(0x00, 0xB8, 0x8A),
> +       _INIT_CMD(0x00, 0xB9, 0xCA),
> +       _INIT_CMD(0x00, 0xBA, 0x0C),
> +       _INIT_CMD(0x00, 0xBB, 0x87),
> +       _INIT_CMD(0x00, 0xBC, 0x06),
> +       _INIT_CMD(0x00, 0xBD, 0x0A),
> +       _INIT_CMD(0x00, 0xBE, 0x9B),
> +       _INIT_CMD(0x00, 0xBF, 0x0C),
> +       _INIT_CMD(0x00, 0xC0, 0x3D),
> +       _INIT_CMD(0x00, 0xC1, 0x71),
> +       _INIT_CMD(0x00, 0xC2, 0x90),
> +       _INIT_CMD(0x00, 0xC3, 0xA0),
> +       _INIT_CMD(0x00, 0xC4, 0xA8),
> +       _INIT_CMD(0x00, 0xC5, 0xB1),
> +       _INIT_CMD(0x00, 0xC6, 0xBB),
> +       _INIT_CMD(0x00, 0xC7, 0xC0),
> +       _INIT_CMD(0x00, 0xC8, 0xC4),
> +       _INIT_CMD(0x00, 0xC9, 0x00),
> +       _INIT_CMD(0x00, 0xCA, 0x00),
> +       _INIT_CMD(0x00, 0xCB, 0x16),
> +       _INIT_CMD(0x00, 0xCC, 0xAF),
> +       _INIT_CMD(0x00, 0xCD, 0xFF),
> +       _INIT_CMD(0x00, 0xCE, 0xFF),
> +       _INIT_CMD(0x00, 0xB0, 0x0B),
> +       _INIT_CMD(0x00, 0xB1, 0x04),
> +       _INIT_CMD(0x00, 0xB2, 0x08),
> +       _INIT_CMD(0x00, 0xB3, 0x19),
> +       _INIT_CMD(0x00, 0xB4, 0x31),
> +       _INIT_CMD(0x00, 0xB5, 0x46),
> +       _INIT_CMD(0x00, 0xB6, 0x55),
> +       _INIT_CMD(0x00, 0xB7, 0x6E),
> +       _INIT_CMD(0x00, 0xB8, 0x92),
> +       _INIT_CMD(0x00, 0xB9, 0xD4),
> +       _INIT_CMD(0x00, 0xBA, 0x1B),
> +       _INIT_CMD(0x00, 0xBB, 0x9B),
> +       _INIT_CMD(0x00, 0xBC, 0x28),
> +       _INIT_CMD(0x00, 0xBD, 0x2D),
> +       _INIT_CMD(0x00, 0xBE, 0xC3),
> +       _INIT_CMD(0x00, 0xBF, 0x2F),
> +       _INIT_CMD(0x00, 0xC0, 0x62),
> +       _INIT_CMD(0x00, 0xC1, 0x99),
> +       _INIT_CMD(0x00, 0xC2, 0xAB),
> +       _INIT_CMD(0x00, 0xC3, 0xBF),
> +       _INIT_CMD(0x00, 0xC4, 0xCF),
> +       _INIT_CMD(0x00, 0xC5, 0xDF),
> +       _INIT_CMD(0x00, 0xC6, 0xF0),
> +       _INIT_CMD(0x00, 0xC7, 0xF9),
> +       _INIT_CMD(0x00, 0xC8, 0xFC),
> +       _INIT_CMD(0x00, 0xC9, 0x00),
> +       _INIT_CMD(0x00, 0xCA, 0x00),
> +       _INIT_CMD(0x00, 0xCB, 0x16),
> +       _INIT_CMD(0x00, 0xCC, 0xAF),
> +       _INIT_CMD(0x00, 0xCD, 0xFF),
> +       _INIT_CMD(0x00, 0xCE, 0xFF),
> +       _INIT_CMD(0x00, 0xB0, 0x0C),
> +       _INIT_CMD(0x00, 0xB1, 0x04),
> +       _INIT_CMD(0x00, 0xB2, 0x05),
> +       _INIT_CMD(0x00, 0xB3, 0x17),
> +       _INIT_CMD(0x00, 0xB4, 0x2E),
> +       _INIT_CMD(0x00, 0xB5, 0x42),
> +       _INIT_CMD(0x00, 0xB6, 0x51),
> +       _INIT_CMD(0x00, 0xB7, 0x69),
> +       _INIT_CMD(0x00, 0xB8, 0x88),
> +       _INIT_CMD(0x00, 0xB9, 0xC9),
> +       _INIT_CMD(0x00, 0xBA, 0x0C),
> +       _INIT_CMD(0x00, 0xBB, 0x86),
> +       _INIT_CMD(0x00, 0xBC, 0x03),
> +       _INIT_CMD(0x00, 0xBD, 0x08),
> +       _INIT_CMD(0x00, 0xBE, 0x95),
> +       _INIT_CMD(0x00, 0xBF, 0x05),
> +       _INIT_CMD(0x00, 0xC0, 0x35),
> +       _INIT_CMD(0x00, 0xC1, 0x62),
> +       _INIT_CMD(0x00, 0xC2, 0x81),
> +       _INIT_CMD(0x00, 0xC3, 0x96),
> +       _INIT_CMD(0x00, 0xC4, 0x9E),
> +       _INIT_CMD(0x00, 0xC5, 0xA5),
> +       _INIT_CMD(0x00, 0xC6, 0xAD),
> +       _INIT_CMD(0x00, 0xC7, 0xB1),
> +       _INIT_CMD(0x00, 0xC8, 0xB4),
> +       _INIT_CMD(0x00, 0xC9, 0x00),
> +       _INIT_CMD(0x00, 0xCA, 0x00),
> +       _INIT_CMD(0x00, 0xCB, 0x16),
> +       _INIT_CMD(0x00, 0xCC, 0xAF),
> +       _INIT_CMD(0x00, 0xCD, 0xFF),
> +       _INIT_CMD(0x00, 0xCE, 0xFF),
> +       _INIT_CMD(0x00, 0xB0, 0x00),
> +       _INIT_CMD(0x00, 0xB3, 0x08),
> +       _INIT_CMD(0x00, 0xB0, 0x04),
> +       _INIT_CMD(0x64, 0xB8, 0x68),
> +
> +       {},
> +};
> +
> +static const struct panel_desc boe_himax8279d10p_panel_desc = {
> +       .display_mode = &default_display_mode,
> +       .bpc = 8,
> +       .width_mm = 135,
> +       .height_mm = 216,
> +       .delay_t1 = 5000,
> +       .reset_delay_t2 = 14000,
> +       .reset_delay_t3 = 1000,
> +       .reset_delay_t4 = 1000,
> +       .reset_delay_t5 = 5000,
> +       .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE
> |
> +                       MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,
> +       .format = MIPI_DSI_FMT_RGB888,
> +       .lanes = 4,
> +       .on_cmds = boe_himax8279d10p_on_cmds,
> +       .off_cmds = default_off_cmds,
> +};
> +
> +static const struct of_device_id panel_of_match[] = {
> +       { .compatible = "boe,himax8279d8p",
> +         .data = &boe_himax8279d8p_panel_desc
> +       }, { .compatible = "boe,himax8279d10p",
> +         .data = &boe_himax8279d10p_panel_desc
> +       }, {
> +               /* sentinel */
> +       }
> +};
> +MODULE_DEVICE_TABLE(of, panel_of_match);
> +
> +static int panel_add(struct panel_info *pinfo)
> +{
> +       struct device *dev = &pinfo->link->dev;
> +       int ret;
> +
> +       pinfo->pp18_gpio = devm_gpiod_get_optional(dev, "pp18",
> GPIOD_OUT_HIGH);
> +       if (IS_ERR(pinfo->pp18_gpio)) {
> +               ret = PTR_ERR(pinfo->pp18_gpio);
> +               if (ret != -EPROBE_DEFER)
> +                       DRM_DEV_ERROR(dev, "failed to get pp18 gpio: %d\n",
> +                                       ret);
> +               return ret;
> +       }
> +
> +       pinfo->pp33_gpio = devm_gpiod_get_optional(dev, "pp33",
> GPIOD_OUT_HIGH);
> +       if (IS_ERR(pinfo->pp33_gpio)) {
> +               ret = PTR_ERR(pinfo->pp33_gpio);
> +               if (ret != -EPROBE_DEFER)
> +                       DRM_DEV_ERROR(dev, "failed to get pp33 gpio: %d\n",
> +                                       ret);
> +               return ret;
> +       }
> +
> +       pinfo->enable_gpio = devm_gpiod_get_optional(dev, "enable",
> +                                                       GPIOD_OUT_HIGH);
> +       if (IS_ERR(pinfo->enable_gpio)) {
> +               ret = PTR_ERR(pinfo->enable_gpio);
> +               if (ret != -EPROBE_DEFER)
> +                       DRM_DEV_ERROR(dev, "failed to get enable gpio:
> %d\n",
> +                                       ret);
> +               return ret;
> +       }
> +
> +       pinfo->backlight = devm_of_find_backlight(dev);
> +       if (IS_ERR(pinfo->backlight))
> +               return PTR_ERR(pinfo->backlight);
> +
> +       drm_panel_init(&pinfo->base);
> +       pinfo->base.funcs = &panel_funcs;
> +       pinfo->base.dev = &pinfo->link->dev;
> +
> +       ret = drm_panel_add(&pinfo->base);
> +       if (ret < 0)
> +               return ret;
> +
> +       return 0;
> +}
> +
> +static void panel_del(struct panel_info *pinfo)
> +{
> +       if (pinfo->base.dev)
> +               drm_panel_remove(&pinfo->base);
> +}
> +
> +static int panel_probe(struct mipi_dsi_device *dsi)
> +{
> +       struct panel_info *pinfo;
> +       const struct panel_desc *desc;
> +       int err;
> +
> +       pinfo = devm_kzalloc(&dsi->dev, sizeof(*pinfo), GFP_KERNEL);
> +       if (!pinfo)
> +               return -ENOMEM;
> +
> +       desc = of_device_get_match_data(&dsi->dev);
> +       dsi->mode_flags = desc->mode_flags;
> +       dsi->format = desc->format;
> +       dsi->lanes = desc->lanes;
> +       pinfo->desc = desc;
> +
> +       pinfo->link = dsi;
> +       mipi_dsi_set_drvdata(dsi, pinfo);
> +
> +       err = panel_add(pinfo);
> +       if (err < 0)
> +               return err;
> +
> +       return mipi_dsi_attach(dsi);
> +}
> +
> +static int panel_remove(struct mipi_dsi_device *dsi)
> +{
> +       struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
> +       int err;
> +
> +       err = boe_panel_unprepare(&pinfo->base);
> +       if (err < 0)
> +               DRM_DEV_ERROR(&dsi->dev, "failed to unprepare panel: %d\n",
> +                               err);
> +
> +       err = boe_panel_disable(&pinfo->base);
> +       if (err < 0)
> +               DRM_DEV_ERROR(&dsi->dev, "failed to disable panel: %d\n",
> err);
> +
> +       err = mipi_dsi_detach(dsi);
> +       if (err < 0)
> +               DRM_DEV_ERROR(&dsi->dev, "failed to detach from DSI host:
> %d\n",
> +                               err);
> +
> +       drm_panel_detach(&pinfo->base);
> +       panel_del(pinfo);
> +
> +       return 0;
> +}
> +
> +static void panel_shutdown(struct mipi_dsi_device *dsi)
> +{
> +       struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
> +
> +       boe_panel_disable(&pinfo->base);
> +       boe_panel_unprepare(&pinfo->base);
> +}
> +
> +static struct mipi_dsi_driver panel_driver = {
> +       .driver = {
> +               .name = "panel-boe-himax8279d",
> +               .of_match_table = panel_of_match,
> +       },
> +       .probe = panel_probe,
> +       .remove = panel_remove,
> +       .shutdown = panel_shutdown,
> +};
> +module_mipi_dsi_driver(panel_driver);
> +
> +MODULE_AUTHOR("Jerry Han <jerry.han.hq@gmail.com>");
> +MODULE_DESCRIPTION("Boe Himax8279d driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.17.1
>
>
<div dir="ltr"><div dir="ltr"><span style="color:rgb(32,33,36);font-size:0.875rem;font-weight:bold;letter-spacing:0.2px;font-family:Roboto,RobotoDraft,Helvetica,Arial,sans-serif;white-space:nowrap">Hi Thierry Reding:</span></div><div dir="ltr"><font color="#202124" face="Roboto, RobotoDraft, Helvetica, Arial, sans-serif"><span style="font-size:14px;letter-spacing:0.2px;white-space:nowrap"><b><br></b></span></font><div><span style="background-color:rgb(247,248,250);color:rgb(51,51,51);font-family:Arial,&quot;Microsoft YaHei&quot;,&quot;\005fae\008f6f\0096c5\009ed1&quot;,&quot;\005b8b\004f53&quot;,&quot;Malgun Gothic&quot;,Meiryo,sans-serif;font-size:13.6px;text-align:justify"><b>Could you please help to check whether there is any problem with the sign-off identity</b></span><font color="#202124" face="Roboto, RobotoDraft, Helvetica, Arial, sans-serif"><span style="font-size:14px;letter-spacing:0.2px;white-space:nowrap"><b>?</b></span><br></font><div><font color="#202124" face="Roboto, RobotoDraft, Helvetica, Arial, sans-serif"><span style="font-size:14px;letter-spacing:0.2px;white-space:nowrap"><b><br></b></span></font></div><div><font color="#202124" face="Roboto, RobotoDraft, Helvetica, Arial, sans-serif"><span style="font-size:14px;letter-spacing:0.2px;white-space:nowrap"><b>Thanks</b></span></font></div></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Jerry Han &lt;<a href="mailto:jerry.han.hq@gmail.com">jerry.han.hq@gmail.com</a>&gt; 于2019年4月25日周四 上午11:27写道:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Support Boe Himax8279d 8.0&quot; 1200x1920 TFT LCD panel, it is a MIPI DSI<br>
panel.<br>
<br>
V8:<br>
- Modify communication address<br>
<br>
V7:<br>
- Add the information of the reviewer<br>
- Remove unnecessary delays, The udelay_range code gracefully returns<br>
    without hitting the scheduler on a delay of 0. (Derek)<br>
- Merge the same data structures, like display_mode and off_cmds (Derek)<br>
- Optimize the processing of results returned by<br>
    devm_gpiod_get_optional (Derek)<br>
<br>
V6:<br>
- Add the information of the reviewer (Sam)<br>
- Delete unnecessary header files #include &lt;linux/fb.h&gt; (Sam)<br>
- The config DRM_PANEL_BOE_HIMAX8279D appears twice. Drop one of them (Sam)<br>
- ADD static, set_gpios function is not used outside this module (Sam)<br>
<br>
V5:<br>
- Added changelog<br>
<br>
V4:<br>
- Frefix all function maes with boe_ (Sam)<br>
- Fsed &quot;enable_gpio&quot; replace &quot;reset_gpio&quot;, Make it look clearer (Sam)<br>
- Sort include lines alphabetically (Sam)<br>
- Fixed entries in the makefile must be sorted alphabetically (Sam)<br>
- Add send_mipi_cmds function to avoid duplicating the code (Sam)<br>
- Add the necessary delay(reset_delay_t5) between reset and sending<br>
    the initialization command (Rock wang)<br>
<br>
V3:<br>
- Remove unnecessary delays in sending initialization commands (Jitao Shi)<br>
<br>
V2:<br>
- Use SPDX identifier (Sam)<br>
- Use necessary header files replace drmP.h (Sam)<br>
- Delete unnecessary header files #include &lt;linux/err.h&gt; (Sam)<br>
- Specifies a GPIOs array to control the reset timing,<br>
    instead of reading &quot;dsi-reset-sequence&quot; data from DTS (Sam)<br>
- Delete backlight_disable() function when already disabled (Sam)<br>
- Use devm_of_find_backlight() replace of_find_backlight_by_node() (Sam)<br>
- Move the necessary data in the DTS to the current file,<br>
    like porch, display_mode and Init code etc. (Sam)<br>
- Add compatible device &quot;boe,himax8279d10p&quot; (Sam)<br>
<br>
Signed-off-by: Jerry Han &lt;<a href="mailto:jerry.han.hq@gmail.com" target="_blank">jerry.han.hq@gmail.com</a>&gt;<br>
Reviewed-by: Sam Ravnborg &lt;<a href="mailto:sam@ravnborg.org" target="_blank">sam@ravnborg.org</a>&gt;<br>
Reviewed-by: Derek Basehore &lt;<a href="mailto:dbasehore@chromium.org" target="_blank">dbasehore@chromium.org</a>&gt;<br>
Cc: Jitao Shi &lt;<a href="mailto:jitao.shi@mediatek.com" target="_blank">jitao.shi@mediatek.com</a>&gt;<br>
Cc: Rock wang &lt;<a href="mailto:rock_wang@himax.com.cn" target="_blank">rock_wang@himax.com.cn</a>&gt;<br>
---<br>
 MAINTAINERS                                  |    6 +<br>
 drivers/gpu/drm/panel/Kconfig                |   11 +<br>
 drivers/gpu/drm/panel/Makefile               |    1 +<br>
 drivers/gpu/drm/panel/panel-boe-himax8279d.c | 1050 ++++++++++++++++++<br>
 4 files changed, 1068 insertions(+)<br>
 create mode 100644 drivers/gpu/drm/panel/panel-boe-himax8279d.c<br>
<br>
diff --git a/MAINTAINERS b/MAINTAINERS<br>
index f8e63bcc4c1c..267468ca72bb 100644<br>
--- a/MAINTAINERS<br>
+++ b/MAINTAINERS<br>
@@ -4816,6 +4816,12 @@ T:       git git://<a href="http://anongit.freedesktop.org/drm/drm-misc" rel="noreferrer" target="_blank">anongit.freedesktop.org/drm/drm-misc</a><br>
 S:     Maintained<br>
 F:     drivers/gpu/drm/bochs/<br>
<br>
+DRM DRIVER FOR BOE HIMAX8279D PANELS<br>
+M:     Jerry Han &lt;<a href="mailto:hanxu5@huaqin.corp-partner.google.com" target="_blank">hanxu5@huaqin.corp-partner.google.com</a>&gt;<br>
+S:     Maintained<br>
+F:     drivers/gpu/drm/panel/panel-boe-himax8279d.c<br>
+F:     Documentation/devicetree/bindings/display/panel/boe,himax8279d.txt<br>
+<br>
 DRM DRIVER FOR FARADAY TVE200 TV ENCODER<br>
 M:     Linus Walleij &lt;<a href="mailto:linus.walleij@linaro.org" target="_blank">linus.walleij@linaro.org</a>&gt;<br>
 T:     git git://<a href="http://anongit.freedesktop.org/drm/drm-misc" rel="noreferrer" target="_blank">anongit.freedesktop.org/drm/drm-misc</a><br>
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig<br>
index f53f817356db..fe2f87cc6627 100644<br>
--- a/drivers/gpu/drm/panel/Kconfig<br>
+++ b/drivers/gpu/drm/panel/Kconfig<br>
@@ -17,6 +17,17 @@ config DRM_PANEL_ARM_VERSATILE<br>
          reference designs. The panel is detected using special registers<br>
          in the Versatile family syscon registers.<br>
<br>
+config DRM_PANEL_BOE_HIMAX8279D<br>
+       tristate &quot;Boe Himax8279d panel&quot;<br>
+       depends on OF<br>
+       depends on DRM_MIPI_DSI<br>
+       depends on BACKLIGHT_CLASS_DEVICE<br>
+       help<br>
+         Say Y here if you want to enable support for Boe Himax8279d<br>
+         TFT-LCD modules. The panel has a 1200x1920 resolution and uses<br>
+         24 bit RGB per pixel. It provides a MIPI DSI interface to<br>
+         the host and has a built-in LED backlight.<br>
+<br>
 config DRM_PANEL_LVDS<br>
        tristate &quot;Generic LVDS panel driver&quot;<br>
        depends on OF<br>
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile<br>
index 7834947a53b0..c4814b6f069e 100644<br>
--- a/drivers/gpu/drm/panel/Makefile<br>
+++ b/drivers/gpu/drm/panel/Makefile<br>
@@ -1,5 +1,6 @@<br>
 # SPDX-License-Identifier: GPL-2.0<br>
 obj-$(CONFIG_DRM_PANEL_ARM_VERSATILE) += panel-arm-versatile.o<br>
+obj-$(CONFIG_DRM_PANEL_BOE_HIMAX8279D) += panel-boe-himax8279d.o<br>
 obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o<br>
 obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o<br>
 obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o<br>
diff --git a/drivers/gpu/drm/panel/panel-boe-himax8279d.c b/drivers/gpu/drm/panel/panel-boe-himax8279d.c<br>
new file mode 100644<br>
index 000000000000..9c8ece4fa30a<br>
--- /dev/null<br>
+++ b/drivers/gpu/drm/panel/panel-boe-himax8279d.c<br>
@@ -0,0 +1,1050 @@<br>
+// SPDX-License-Identifier: GPL-2.0<br>
+/*<br>
+ * Copyright (c) 2019, Huaqin Telecom Technology Co., Ltd<br>
+ *<br>
+ * Author: Jerry Han &lt;<a href="mailto:jerry.han.hq@gmail.com" target="_blank">jerry.han.hq@gmail.com</a>&gt;<br>
+ *<br>
+ */<br>
+<br>
+#include &lt;linux/backlight.h&gt;<br>
+#include &lt;linux/delay.h&gt;<br>
+#include &lt;linux/kernel.h&gt;<br>
+#include &lt;linux/module.h&gt;<br>
+#include &lt;linux/of.h&gt;<br>
+#include &lt;linux/of_device.h&gt;<br>
+<br>
+#include &lt;linux/gpio/consumer.h&gt;<br>
+#include &lt;linux/regulator/consumer.h&gt;<br>
+<br>
+#include &lt;drm/drm_device.h&gt;<br>
+#include &lt;drm/drm_mipi_dsi.h&gt;<br>
+#include &lt;drm/drm_modes.h&gt;<br>
+#include &lt;drm/drm_panel.h&gt;<br>
+#include &lt;drm/drm_print.h&gt;<br>
+<br>
+#include &lt;video/mipi_display.h&gt;<br>
+<br>
+struct panel_cmd {<br>
+       size_t len;<br>
+       const char *data;<br>
+};<br>
+<br>
+#define _INIT_CMD(...) { \<br>
+       .len = sizeof((char[]){__VA_ARGS__}), \<br>
+       .data = (char[]){__VA_ARGS__} }<br>
+<br>
+struct panel_desc {<br>
+       const struct drm_display_mode *display_mode;<br>
+       unsigned int bpc;<br>
+       unsigned int width_mm;<br>
+       unsigned int height_mm;<br>
+<br>
+       unsigned int delay_t1;<br>
+       unsigned int reset_delay_t2;<br>
+       unsigned int reset_delay_t3;<br>
+       unsigned int reset_delay_t4;<br>
+       unsigned int reset_delay_t5;<br>
+<br>
+       unsigned long mode_flags;<br>
+       enum mipi_dsi_pixel_format format;<br>
+       unsigned int lanes;<br>
+       const struct panel_cmd *on_cmds;<br>
+       const struct panel_cmd *off_cmds;<br>
+};<br>
+<br>
+struct panel_info {<br>
+       struct drm_panel base;<br>
+       struct mipi_dsi_device *link;<br>
+       const struct panel_desc *desc;<br>
+<br>
+       struct backlight_device *backlight;<br>
+       struct gpio_desc *enable_gpio;<br>
+       struct gpio_desc *pp33_gpio;<br>
+       struct gpio_desc *pp18_gpio;<br>
+<br>
+       bool prepared;<br>
+       bool enabled;<br>
+};<br>
+<br>
+static inline struct panel_info *to_panel_info(struct drm_panel *panel)<br>
+{<br>
+       return container_of(panel, struct panel_info, base);<br>
+}<br>
+<br>
+static void set_gpios(struct panel_info *pinfo, int enable)<br>
+{<br>
+       gpiod_set_value(pinfo-&gt;enable_gpio, enable);<br>
+       gpiod_set_value(pinfo-&gt;pp33_gpio, enable);<br>
+       gpiod_set_value(pinfo-&gt;pp18_gpio, enable);<br>
+}<br>
+<br>
+static int send_mipi_cmds(struct drm_panel *panel, const struct panel_cmd *cmds)<br>
+{<br>
+       struct panel_info *pinfo = to_panel_info(panel);<br>
+       unsigned int i = 0;<br>
+       int err;<br>
+<br>
+       if (!cmds)<br>
+               return -EFAULT;<br>
+<br>
+       for (i = 0; cmds[i].len != 0; i++) {<br>
+               const struct panel_cmd *cmd = &amp;cmds[i];<br>
+<br>
+               if (cmd-&gt;len == 2)<br>
+                       err = mipi_dsi_dcs_write(pinfo-&gt;link,<br>
+                                                   cmd-&gt;data[1], NULL, 0);<br>
+               else<br>
+                       err = mipi_dsi_dcs_write(pinfo-&gt;link,<br>
+                                                   cmd-&gt;data[1], cmd-&gt;data + 2,<br>
+                                                   cmd-&gt;len - 2);<br>
+<br>
+               if (err &lt; 0)<br>
+                       return err;<br>
+<br>
+               usleep_range((cmd-&gt;data[0]) * 1000,<br>
+                           (1 + cmd-&gt;data[0]) * 1000);<br>
+       }<br>
+<br>
+       return 0;<br>
+}<br>
+<br>
+static int boe_panel_disable(struct drm_panel *panel)<br>
+{<br>
+       struct panel_info *pinfo = to_panel_info(panel);<br>
+<br>
+       backlight_disable(pinfo-&gt;backlight);<br>
+<br>
+       pinfo-&gt;enabled = false;<br>
+<br>
+       return 0;<br>
+}<br>
+<br>
+static int boe_panel_unprepare(struct drm_panel *panel)<br>
+{<br>
+       struct panel_info *pinfo = to_panel_info(panel);<br>
+       int err;<br>
+<br>
+       if (!pinfo-&gt;prepared)<br>
+               return 0;<br>
+<br>
+       /* send off code */<br>
+       err = send_mipi_cmds(panel, pinfo-&gt;desc-&gt;off_cmds);<br>
+       if (err &lt; 0) {<br>
+               DRM_DEV_ERROR(panel-&gt;dev,<br>
+                               &quot;failed to send DCS Off Code: %d\n&quot;, err);<br>
+               goto poweroff;<br>
+       }<br>
+<br>
+       set_gpios(pinfo, 0);<br>
+<br>
+       pinfo-&gt;prepared = false;<br>
+<br>
+       return 0;<br>
+<br>
+poweroff:<br>
+       set_gpios(pinfo, 0);<br>
+       return err;<br>
+}<br>
+<br>
+static int boe_panel_prepare(struct drm_panel *panel)<br>
+{<br>
+       struct panel_info *pinfo = to_panel_info(panel);<br>
+       const struct panel_desc *desc = pinfo-&gt;desc;<br>
+       int err;<br>
+<br>
+       if (pinfo-&gt;prepared)<br>
+               return 0;<br>
+<br>
+       gpiod_set_value(pinfo-&gt;pp18_gpio, 1);<br>
+       /* T1 (&gt; 5ms) */<br>
+       usleep_range(desc-&gt;delay_t1, 1000 + desc-&gt;delay_t1);<br>
+       gpiod_set_value(pinfo-&gt;pp33_gpio, 1);<br>
+<br>
+       /* reset sequence */<br>
+       usleep_range(desc-&gt;reset_delay_t2, 1000 + desc-&gt;reset_delay_t2);<br>
+<br>
+       gpiod_set_value(pinfo-&gt;enable_gpio, 1);<br>
+       usleep_range(desc-&gt;reset_delay_t3, 1000 + desc-&gt;reset_delay_t3);<br>
+       gpiod_set_value(pinfo-&gt;enable_gpio, 0);<br>
+<br>
+       usleep_range(desc-&gt;reset_delay_t4, 1000 + desc-&gt;reset_delay_t4);<br>
+       gpiod_set_value(pinfo-&gt;enable_gpio, 1);<br>
+<br>
+       usleep_range(desc-&gt;reset_delay_t5, 1000 + desc-&gt;reset_delay_t5);<br>
+<br>
+       /* send init code */<br>
+       err = send_mipi_cmds(panel, pinfo-&gt;desc-&gt;on_cmds);<br>
+       if (err &lt; 0) {<br>
+               DRM_DEV_ERROR(panel-&gt;dev,<br>
+                               &quot;failed to send DCS Init Code: %d\n&quot;, err);<br>
+               goto poweroff;<br>
+       }<br>
+<br>
+       pinfo-&gt;prepared = true;<br>
+<br>
+       return 0;<br>
+<br>
+poweroff:<br>
+       set_gpios(pinfo, 0);<br>
+       return err;<br>
+}<br>
+<br>
+static int boe_panel_enable(struct drm_panel *panel)<br>
+{<br>
+       struct panel_info *pinfo = to_panel_info(panel);<br>
+       int ret;<br>
+<br>
+       if (pinfo-&gt;enabled)<br>
+               return 0;<br>
+<br>
+       ret = backlight_enable(pinfo-&gt;backlight);<br>
+       if (ret) {<br>
+               DRM_DEV_ERROR(panel-&gt;drm-&gt;dev,<br>
+                               &quot;Failed to enable backlight %d\n&quot;, ret);<br>
+               return ret;<br>
+       }<br>
+<br>
+       pinfo-&gt;enabled = true;<br>
+<br>
+       return 0;<br>
+}<br>
+<br>
+static int boe_panel_get_modes(struct drm_panel *panel)<br>
+{<br>
+       struct panel_info *pinfo = to_panel_info(panel);<br>
+       const struct drm_display_mode *m = pinfo-&gt;desc-&gt;display_mode;<br>
+       struct drm_display_mode *mode;<br>
+<br>
+       mode = drm_mode_duplicate(panel-&gt;drm, m);<br>
+       if (!mode) {<br>
+               DRM_DEV_ERROR(panel-&gt;drm-&gt;dev, &quot;failed to add mode %ux%u@%u\n&quot;,<br>
+                               m-&gt;hdisplay, m-&gt;vdisplay, m-&gt;vrefresh);<br>
+               return -ENOMEM;<br>
+       }<br>
+<br>
+       drm_mode_set_name(mode);<br>
+<br>
+       drm_mode_probed_add(panel-&gt;connector, mode);<br>
+<br>
+       panel-&gt;connector-&gt;display_info.width_mm = pinfo-&gt;desc-&gt;width_mm;<br>
+       panel-&gt;connector-&gt;display_info.height_mm = pinfo-&gt;desc-&gt;height_mm;<br>
+       panel-&gt;connector-&gt;display_info.bpc = pinfo-&gt;desc-&gt;bpc;<br>
+<br>
+       return 1;<br>
+}<br>
+<br>
+static const struct drm_panel_funcs panel_funcs = {<br>
+       .disable = boe_panel_disable,<br>
+       .unprepare = boe_panel_unprepare,<br>
+       .prepare = boe_panel_prepare,<br>
+       .enable = boe_panel_enable,<br>
+       .get_modes = boe_panel_get_modes,<br>
+};<br>
+<br>
+static const struct drm_display_mode default_display_mode = {<br>
+       .clock = 159420,<br>
+       .hdisplay = 1200,<br>
+       .hsync_start = 1200 + 80,<br>
+       .hsync_end = 1200 + 80 + 60,<br>
+       .htotal = 1200 + 80 + 60 + 24,<br>
+       .vdisplay = 1920,<br>
+       .vsync_start = 1920 + 10,<br>
+       .vsync_end = 1920 + 10 + 14,<br>
+       .vtotal = 1920 + 10 + 14 + 4,<br>
+       .vrefresh = 60,<br>
+};<br>
+<br>
+static const struct panel_cmd default_off_cmds[] = {<br>
+       _INIT_CMD(0x00, 0x28),<br>
+       _INIT_CMD(0x01, 0x10),<br>
+<br>
+       {},<br>
+};<br>
+<br>
+/* 8 inch */<br>
+static const struct panel_cmd boe_himax8279d8p_on_cmds[] = {<br>
+       _INIT_CMD(0x22, 0x10),<br>
+       _INIT_CMD(0x00, 0xB0, 0x05),<br>
+       _INIT_CMD(0x00, 0xB1, 0xE5),<br>
+       _INIT_CMD(0x00, 0xB3, 0x52),<br>
+       _INIT_CMD(0x00, 0xB0, 0x00),<br>
+       _INIT_CMD(0x00, 0xB3, 0x88),<br>
+       _INIT_CMD(0x00, 0xB0, 0x04),<br>
+       _INIT_CMD(0x00, 0xB8, 0x00),<br>
+       _INIT_CMD(0x00, 0xB0, 0x00),<br>
+       _INIT_CMD(0x00, 0xB2, 0x50),<br>
+       _INIT_CMD(0x00, 0xB6, 0x03),<br>
+       _INIT_CMD(0x00, 0xBA, 0x8B),<br>
+       _INIT_CMD(0x00, 0xBF, 0x15),<br>
+       _INIT_CMD(0x00, 0xC0, 0x0F),<br>
+       _INIT_CMD(0x00, 0xC2, 0x0C),<br>
+       _INIT_CMD(0x00, 0xC3, 0x02),<br>
+       _INIT_CMD(0x00, 0xC4, 0x0C),<br>
+       _INIT_CMD(0x00, 0xC5, 0x02),<br>
+       _INIT_CMD(0x00, 0xB0, 0x01),<br>
+       _INIT_CMD(0x00, 0xE0, 0x26),<br>
+       _INIT_CMD(0x00, 0xE1, 0x26),<br>
+       _INIT_CMD(0x00, 0xDC, 0x00),<br>
+       _INIT_CMD(0x00, 0xDD, 0x00),<br>
+       _INIT_CMD(0x00, 0xCC, 0x26),<br>
+       _INIT_CMD(0x00, 0xCD, 0x26),<br>
+       _INIT_CMD(0x00, 0xC8, 0x00),<br>
+       _INIT_CMD(0x00, 0xC9, 0x00),<br>
+       _INIT_CMD(0x00, 0xD2, 0x04),<br>
+       _INIT_CMD(0x00, 0xD3, 0x04),<br>
+       _INIT_CMD(0x00, 0xE6, 0x03),<br>
+       _INIT_CMD(0x00, 0xE7, 0x03),<br>
+       _INIT_CMD(0x00, 0xC4, 0x08),<br>
+       _INIT_CMD(0x00, 0xC5, 0x08),<br>
+       _INIT_CMD(0x00, 0xD8, 0x07),<br>
+       _INIT_CMD(0x00, 0xD9, 0x07),<br>
+       _INIT_CMD(0x00, 0xC2, 0x06),<br>
+       _INIT_CMD(0x00, 0xC3, 0x06),<br>
+       _INIT_CMD(0x00, 0xD6, 0x05),<br>
+       _INIT_CMD(0x00, 0xD7, 0x05),<br>
+       _INIT_CMD(0x00, 0xC0, 0x0C),<br>
+       _INIT_CMD(0x00, 0xC1, 0x0C),<br>
+       _INIT_CMD(0x00, 0xD4, 0x0B),<br>
+       _INIT_CMD(0x00, 0xD5, 0x0B),<br>
+       _INIT_CMD(0x00, 0xCA, 0x0A),<br>
+       _INIT_CMD(0x00, 0xCB, 0x0A),<br>
+       _INIT_CMD(0x00, 0xDE, 0x09),<br>
+       _INIT_CMD(0x00, 0xDF, 0x09),<br>
+       _INIT_CMD(0x00, 0xC6, 0x26),<br>
+       _INIT_CMD(0x00, 0xC7, 0x26),<br>
+       _INIT_CMD(0x00, 0xCE, 0x00),<br>
+       _INIT_CMD(0x00, 0xCF, 0x00),<br>
+       _INIT_CMD(0x00, 0xDA, 0x26),<br>
+       _INIT_CMD(0x00, 0xDB, 0x26),<br>
+       _INIT_CMD(0x00, 0xE2, 0x00),<br>
+       _INIT_CMD(0x00, 0xE3, 0x00),<br>
+       _INIT_CMD(0x00, 0xB0, 0x02),<br>
+       _INIT_CMD(0x00, 0xC0, 0x00),<br>
+       _INIT_CMD(0x00, 0xC1, 0x07),<br>
+       _INIT_CMD(0x00, 0xC2, 0x0D),<br>
+       _INIT_CMD(0x00, 0xC3, 0x18),<br>
+       _INIT_CMD(0x00, 0xC4, 0x27),<br>
+       _INIT_CMD(0x00, 0xC5, 0x28),<br>
+       _INIT_CMD(0x00, 0xC6, 0x30),<br>
+       _INIT_CMD(0x00, 0xC7, 0x2E),<br>
+       _INIT_CMD(0x00, 0xC8, 0x2F),<br>
+       _INIT_CMD(0x00, 0xC9, 0x1A),<br>
+       _INIT_CMD(0x00, 0xCA, 0x20),<br>
+       _INIT_CMD(0x00, 0xCB, 0x29),<br>
+       _INIT_CMD(0x00, 0xCC, 0x26),<br>
+       _INIT_CMD(0x00, 0xCD, 0x32),<br>
+       _INIT_CMD(0x00, 0xCE, 0x33),<br>
+       _INIT_CMD(0x00, 0xCF, 0x31),<br>
+       _INIT_CMD(0x00, 0xD0, 0x06),<br>
+       _INIT_CMD(0x00, 0xD2, 0x00),<br>
+       _INIT_CMD(0x00, 0xD3, 0x07),<br>
+       _INIT_CMD(0x00, 0xD4, 0x12),<br>
+       _INIT_CMD(0x00, 0xD5, 0x26),<br>
+       _INIT_CMD(0x00, 0xD6, 0x3D),<br>
+       _INIT_CMD(0x00, 0xD7, 0x3F),<br>
+       _INIT_CMD(0x00, 0xD8, 0x3F),<br>
+       _INIT_CMD(0x00, 0xD9, 0x3F),<br>
+       _INIT_CMD(0x00, 0xDA, 0x3F),<br>
+       _INIT_CMD(0x00, 0xDB, 0x3F),<br>
+       _INIT_CMD(0x00, 0xDC, 0x3F),<br>
+       _INIT_CMD(0x00, 0xDD, 0x3F),<br>
+       _INIT_CMD(0x00, 0xDE, 0x3F),<br>
+       _INIT_CMD(0x00, 0xDF, 0x3A),<br>
+       _INIT_CMD(0x00, 0xE0, 0x37),<br>
+       _INIT_CMD(0x00, 0xE1, 0x35),<br>
+       _INIT_CMD(0x00, 0xE2, 0x07),<br>
+       _INIT_CMD(0x00, 0xB0, 0x03),<br>
+       _INIT_CMD(0x00, 0xC8, 0x0B),<br>
+       _INIT_CMD(0x00, 0xC9, 0x07),<br>
+       _INIT_CMD(0x00, 0xC3, 0x00),<br>
+       _INIT_CMD(0x00, 0xE7, 0x00),<br>
+       _INIT_CMD(0x00, 0xC5, 0x2A),<br>
+       _INIT_CMD(0x00, 0xDE, 0x2A),<br>
+       _INIT_CMD(0x00, 0xCA, 0x43),<br>
+       _INIT_CMD(0x00, 0xC9, 0x07),<br>
+       _INIT_CMD(0x00, 0xE4, 0xC0),<br>
+       _INIT_CMD(0x00, 0xE5, 0x0D),<br>
+       _INIT_CMD(0x00, 0xCB, 0x00),<br>
+       _INIT_CMD(0x00, 0xB0, 0x06),<br>
+       _INIT_CMD(0x00, 0xB8, 0xA5),<br>
+       _INIT_CMD(0x00, 0xC0, 0xA5),<br>
+       _INIT_CMD(0x00, 0xC7, 0x0F),<br>
+       _INIT_CMD(0x00, 0xD5, 0x32),<br>
+       _INIT_CMD(0x00, 0xB8, 0x00),<br>
+       _INIT_CMD(0x00, 0xC0, 0x00),<br>
+       _INIT_CMD(0x00, 0xBC, 0x00),<br>
+       _INIT_CMD(0x00, 0xB0, 0x07),<br>
+       _INIT_CMD(0x00, 0xB1, 0x00),<br>
+       _INIT_CMD(0x00, 0xB2, 0x09),<br>
+       _INIT_CMD(0x00, 0xB3, 0x19),<br>
+       _INIT_CMD(0x00, 0xB4, 0x2F),<br>
+       _INIT_CMD(0x00, 0xB5, 0x44),<br>
+       _INIT_CMD(0x00, 0xB6, 0x52),<br>
+       _INIT_CMD(0x00, 0xB7, 0x6A),<br>
+       _INIT_CMD(0x00, 0xB8, 0x8A),<br>
+       _INIT_CMD(0x00, 0xB9, 0xCA),<br>
+       _INIT_CMD(0x00, 0xBA, 0x0C),<br>
+       _INIT_CMD(0x05, 0xBB, 0x87),<br>
+       _INIT_CMD(0x00, 0xBC, 0x06),<br>
+       _INIT_CMD(0x00, 0xBD, 0x0A),<br>
+       _INIT_CMD(0x00, 0xBE, 0x9B),<br>
+       _INIT_CMD(0x00, 0xBF, 0x0C),<br>
+       _INIT_CMD(0x00, 0xC0, 0x3D),<br>
+       _INIT_CMD(0x00, 0xC1, 0x71),<br>
+       _INIT_CMD(0x00, 0xC2, 0x90),<br>
+       _INIT_CMD(0x00, 0xC3, 0xA0),<br>
+       _INIT_CMD(0x00, 0xC4, 0xA8),<br>
+       _INIT_CMD(0x00, 0xC5, 0xB1),<br>
+       _INIT_CMD(0x00, 0xC6, 0xBB),<br>
+       _INIT_CMD(0x00, 0xC7, 0xC0),<br>
+       _INIT_CMD(0x00, 0xC8, 0xC4),<br>
+       _INIT_CMD(0x00, 0xC9, 0x00),<br>
+       _INIT_CMD(0x00, 0xCA, 0x00),<br>
+       _INIT_CMD(0x00, 0xCB, 0x16),<br>
+       _INIT_CMD(0x00, 0xCC, 0xAF),<br>
+       _INIT_CMD(0x00, 0xCD, 0xFF),<br>
+       _INIT_CMD(0x00, 0xCE, 0xFF),<br>
+       _INIT_CMD(0x00, 0xB0, 0x08),<br>
+       _INIT_CMD(0x00, 0xB1, 0x04),<br>
+       _INIT_CMD(0x00, 0xB2, 0x08),<br>
+       _INIT_CMD(0x00, 0xB3, 0x19),<br>
+       _INIT_CMD(0x00, 0xB4, 0x31),<br>
+       _INIT_CMD(0x00, 0xB5, 0x46),<br>
+       _INIT_CMD(0x00, 0xB6, 0x55),<br>
+       _INIT_CMD(0x00, 0xB7, 0x6E),<br>
+       _INIT_CMD(0x00, 0xB8, 0x92),<br>
+       _INIT_CMD(0x00, 0xB9, 0xD4),<br>
+       _INIT_CMD(0x00, 0xBA, 0x1B),<br>
+       _INIT_CMD(0x05, 0xBB, 0x9B),<br>
+       _INIT_CMD(0x00, 0xBC, 0x28),<br>
+       _INIT_CMD(0x00, 0xBD, 0x2D),<br>
+       _INIT_CMD(0x00, 0xBE, 0xC3),<br>
+       _INIT_CMD(0x00, 0xBF, 0x2F),<br>
+       _INIT_CMD(0x00, 0xC0, 0x62),<br>
+       _INIT_CMD(0x00, 0xC1, 0x99),<br>
+       _INIT_CMD(0x00, 0xC2, 0xAB),<br>
+       _INIT_CMD(0x00, 0xC3, 0xBF),<br>
+       _INIT_CMD(0x00, 0xC4, 0xCF),<br>
+       _INIT_CMD(0x00, 0xC5, 0xDF),<br>
+       _INIT_CMD(0x00, 0xC6, 0xF0),<br>
+       _INIT_CMD(0x00, 0xC7, 0xF9),<br>
+       _INIT_CMD(0x00, 0xC8, 0xFC),<br>
+       _INIT_CMD(0x00, 0xC9, 0x00),<br>
+       _INIT_CMD(0x00, 0xCA, 0x00),<br>
+       _INIT_CMD(0x00, 0xCB, 0x16),<br>
+       _INIT_CMD(0x00, 0xCC, 0xAF),<br>
+       _INIT_CMD(0x00, 0xCD, 0xFF),<br>
+       _INIT_CMD(0x00, 0xCE, 0xFF),<br>
+       _INIT_CMD(0x00, 0xB0, 0x09),<br>
+       _INIT_CMD(0x00, 0xB1, 0x04),<br>
+       _INIT_CMD(0x00, 0xB2, 0x05),<br>
+       _INIT_CMD(0x00, 0xB3, 0x17),<br>
+       _INIT_CMD(0x00, 0xB4, 0x2E),<br>
+       _INIT_CMD(0x00, 0xB5, 0x42),<br>
+       _INIT_CMD(0x00, 0xB6, 0x51),<br>
+       _INIT_CMD(0x00, 0xB7, 0x69),<br>
+       _INIT_CMD(0x00, 0xB8, 0x88),<br>
+       _INIT_CMD(0x00, 0xB9, 0xC9),<br>
+       _INIT_CMD(0x00, 0xBA, 0x0C),<br>
+       _INIT_CMD(0x05, 0xBB, 0x86),<br>
+       _INIT_CMD(0x00, 0xBC, 0x03),<br>
+       _INIT_CMD(0x00, 0xBD, 0x08),<br>
+       _INIT_CMD(0x00, 0xBE, 0x95),<br>
+       _INIT_CMD(0x00, 0xBF, 0x05),<br>
+       _INIT_CMD(0x00, 0xC0, 0x35),<br>
+       _INIT_CMD(0x00, 0xC1, 0x62),<br>
+       _INIT_CMD(0x00, 0xC2, 0x81),<br>
+       _INIT_CMD(0x00, 0xC3, 0x96),<br>
+       _INIT_CMD(0x00, 0xC4, 0x9E),<br>
+       _INIT_CMD(0x00, 0xC5, 0xA5),<br>
+       _INIT_CMD(0x00, 0xC6, 0xAD),<br>
+       _INIT_CMD(0x00, 0xC7, 0xB1),<br>
+       _INIT_CMD(0x00, 0xC8, 0xB4),<br>
+       _INIT_CMD(0x00, 0xC9, 0x00),<br>
+       _INIT_CMD(0x00, 0xCA, 0x00),<br>
+       _INIT_CMD(0x00, 0xCB, 0x16),<br>
+       _INIT_CMD(0x00, 0xCC, 0xAF),<br>
+       _INIT_CMD(0x00, 0xCD, 0xFF),<br>
+       _INIT_CMD(0x00, 0xCE, 0xFF),<br>
+       _INIT_CMD(0x00, 0xB0, 0x0A),<br>
+       _INIT_CMD(0x00, 0xB1, 0x00),<br>
+       _INIT_CMD(0x00, 0xB2, 0x09),<br>
+       _INIT_CMD(0x00, 0xB3, 0x19),<br>
+       _INIT_CMD(0x00, 0xB4, 0x2F),<br>
+       _INIT_CMD(0x00, 0xB5, 0x44),<br>
+       _INIT_CMD(0x00, 0xB6, 0x52),<br>
+       _INIT_CMD(0x00, 0xB7, 0x6A),<br>
+       _INIT_CMD(0x00, 0xB8, 0x8A),<br>
+       _INIT_CMD(0x00, 0xB9, 0xCA),<br>
+       _INIT_CMD(0x00, 0xBA, 0x0C),<br>
+       _INIT_CMD(0x05, 0xBB, 0x87),<br>
+       _INIT_CMD(0x00, 0xBC, 0x06),<br>
+       _INIT_CMD(0x00, 0xBD, 0x0A),<br>
+       _INIT_CMD(0x00, 0xBE, 0x9B),<br>
+       _INIT_CMD(0x00, 0xBF, 0x0C),<br>
+       _INIT_CMD(0x00, 0xC0, 0x3D),<br>
+       _INIT_CMD(0x00, 0xC1, 0x71),<br>
+       _INIT_CMD(0x00, 0xC2, 0x90),<br>
+       _INIT_CMD(0x00, 0xC3, 0xA0),<br>
+       _INIT_CMD(0x00, 0xC4, 0xA8),<br>
+       _INIT_CMD(0x00, 0xC5, 0xB1),<br>
+       _INIT_CMD(0x00, 0xC6, 0xBB),<br>
+       _INIT_CMD(0x00, 0xC7, 0xC0),<br>
+       _INIT_CMD(0x00, 0xC8, 0xC4),<br>
+       _INIT_CMD(0x00, 0xC9, 0x00),<br>
+       _INIT_CMD(0x00, 0xCA, 0x00),<br>
+       _INIT_CMD(0x00, 0xCB, 0x16),<br>
+       _INIT_CMD(0x00, 0xCC, 0xAF),<br>
+       _INIT_CMD(0x00, 0xCD, 0xFF),<br>
+       _INIT_CMD(0x00, 0xCE, 0xFF),<br>
+       _INIT_CMD(0x00, 0xB0, 0x0B),<br>
+       _INIT_CMD(0x00, 0xB1, 0x04),<br>
+       _INIT_CMD(0x00, 0xB2, 0x08),<br>
+       _INIT_CMD(0x00, 0xB3, 0x19),<br>
+       _INIT_CMD(0x00, 0xB4, 0x31),<br>
+       _INIT_CMD(0x00, 0xB5, 0x46),<br>
+       _INIT_CMD(0x00, 0xB6, 0x55),<br>
+       _INIT_CMD(0x00, 0xB7, 0x6E),<br>
+       _INIT_CMD(0x00, 0xB8, 0x92),<br>
+       _INIT_CMD(0x00, 0xB9, 0xD4),<br>
+       _INIT_CMD(0x00, 0xBA, 0x1B),<br>
+       _INIT_CMD(0x05, 0xBB, 0x9B),<br>
+       _INIT_CMD(0x00, 0xBC, 0x28),<br>
+       _INIT_CMD(0x00, 0xBD, 0x2D),<br>
+       _INIT_CMD(0x00, 0xBE, 0xC3),<br>
+       _INIT_CMD(0x00, 0xBF, 0x2F),<br>
+       _INIT_CMD(0x00, 0xC0, 0x62),<br>
+       _INIT_CMD(0x00, 0xC1, 0x99),<br>
+       _INIT_CMD(0x00, 0xC2, 0xAB),<br>
+       _INIT_CMD(0x00, 0xC3, 0xBF),<br>
+       _INIT_CMD(0x00, 0xC4, 0xCF),<br>
+       _INIT_CMD(0x00, 0xC5, 0xDF),<br>
+       _INIT_CMD(0x00, 0xC6, 0xF0),<br>
+       _INIT_CMD(0x00, 0xC7, 0xF9),<br>
+       _INIT_CMD(0x00, 0xC8, 0xFC),<br>
+       _INIT_CMD(0x00, 0xC9, 0x00),<br>
+       _INIT_CMD(0x00, 0xCA, 0x00),<br>
+       _INIT_CMD(0x00, 0xCB, 0x16),<br>
+       _INIT_CMD(0x00, 0xCC, 0xAF),<br>
+       _INIT_CMD(0x00, 0xCD, 0xFF),<br>
+       _INIT_CMD(0x00, 0xCE, 0xFF),<br>
+       _INIT_CMD(0x00, 0xB0, 0x0C),<br>
+       _INIT_CMD(0x00, 0xB1, 0x04),<br>
+       _INIT_CMD(0x00, 0xB2, 0x05),<br>
+       _INIT_CMD(0x00, 0xB3, 0x17),<br>
+       _INIT_CMD(0x00, 0xB4, 0x2E),<br>
+       _INIT_CMD(0x00, 0xB5, 0x42),<br>
+       _INIT_CMD(0x00, 0xB6, 0x51),<br>
+       _INIT_CMD(0x00, 0xB7, 0x69),<br>
+       _INIT_CMD(0x00, 0xB8, 0x88),<br>
+       _INIT_CMD(0x00, 0xB9, 0xC9),<br>
+       _INIT_CMD(0x00, 0xBA, 0x0C),<br>
+       _INIT_CMD(0x05, 0xBB, 0x86),<br>
+       _INIT_CMD(0x00, 0xBC, 0x03),<br>
+       _INIT_CMD(0x00, 0xBD, 0x08),<br>
+       _INIT_CMD(0x00, 0xBE, 0x95),<br>
+       _INIT_CMD(0x00, 0xBF, 0x05),<br>
+       _INIT_CMD(0x00, 0xC0, 0x35),<br>
+       _INIT_CMD(0x00, 0xC1, 0x62),<br>
+       _INIT_CMD(0x00, 0xC2, 0x81),<br>
+       _INIT_CMD(0x00, 0xC3, 0x96),<br>
+       _INIT_CMD(0x00, 0xC4, 0x9E),<br>
+       _INIT_CMD(0x00, 0xC5, 0xA5),<br>
+       _INIT_CMD(0x00, 0xC6, 0xAD),<br>
+       _INIT_CMD(0x00, 0xC7, 0xB1),<br>
+       _INIT_CMD(0x00, 0xC8, 0xB4),<br>
+       _INIT_CMD(0x00, 0xC9, 0x00),<br>
+       _INIT_CMD(0x00, 0xCA, 0x00),<br>
+       _INIT_CMD(0x00, 0xCB, 0x16),<br>
+       _INIT_CMD(0x00, 0xCC, 0xAF),<br>
+       _INIT_CMD(0x00, 0xCD, 0xFF),<br>
+       _INIT_CMD(0x64, 0xCE, 0xFF),<br>
+       _INIT_CMD(0x00, 0xB0, 0x00),<br>
+       _INIT_CMD(0x00, 0xB3, 0x08),<br>
+       _INIT_CMD(0x00, 0xB0, 0x04),<br>
+       _INIT_CMD(0x0A, 0xB8, 0x68),<br>
+       _INIT_CMD(0x78, 0x11),<br>
+       _INIT_CMD(0x14, 0x29),<br>
+<br>
+       {},<br>
+};<br>
+<br>
+static const struct panel_desc boe_himax8279d8p_panel_desc = {<br>
+       .display_mode = &amp;default_display_mode,<br>
+       .bpc = 8,<br>
+       .width_mm = 107,<br>
+       .height_mm = 172,<br>
+       .delay_t1 = 5000,<br>
+       .reset_delay_t2 = 14000,<br>
+       .reset_delay_t3 = 1000,<br>
+       .reset_delay_t4 = 1000,<br>
+       .reset_delay_t5 = 5000,<br>
+       .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |<br>
+                       MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,<br>
+       .format = MIPI_DSI_FMT_RGB888,<br>
+       .lanes = 4,<br>
+       .on_cmds = boe_himax8279d8p_on_cmds,<br>
+       .off_cmds = default_off_cmds,<br>
+};<br>
+<br>
+/* 10 inch */<br>
+static const struct panel_cmd boe_himax8279d10p_on_cmds[] = {<br>
+       _INIT_CMD(0x00, 0xB0, 0x05),<br>
+       _INIT_CMD(0x00, 0xB1, 0xE5),<br>
+       _INIT_CMD(0x00, 0xB3, 0x52),<br>
+       _INIT_CMD(0x00, 0xB0, 0x00),<br>
+       _INIT_CMD(0x00, 0xB3, 0x88),<br>
+       _INIT_CMD(0x00, 0xB0, 0x04),<br>
+       _INIT_CMD(0x00, 0xB8, 0x00),<br>
+       _INIT_CMD(0x00, 0xB0, 0x00),<br>
+       _INIT_CMD(0x00, 0xB2, 0x50),<br>
+       _INIT_CMD(0x00, 0xB6, 0x03),<br>
+       _INIT_CMD(0x00, 0xBA, 0x8B),<br>
+       _INIT_CMD(0x00, 0xBF, 0x1A),<br>
+       _INIT_CMD(0x00, 0xC0, 0x0F),<br>
+       _INIT_CMD(0x00, 0xC2, 0x0C),<br>
+       _INIT_CMD(0x00, 0xC3, 0x02),<br>
+       _INIT_CMD(0x00, 0xC4, 0x0C),<br>
+       _INIT_CMD(0x00, 0xC5, 0x02),<br>
+       _INIT_CMD(0x00, 0xB0, 0x01),<br>
+       _INIT_CMD(0x00, 0xE0, 0x26),<br>
+       _INIT_CMD(0x00, 0xE1, 0x26),<br>
+       _INIT_CMD(0x00, 0xDC, 0x00),<br>
+       _INIT_CMD(0x00, 0xDD, 0x00),<br>
+       _INIT_CMD(0x00, 0xCC, 0x26),<br>
+       _INIT_CMD(0x00, 0xCD, 0x26),<br>
+       _INIT_CMD(0x00, 0xC8, 0x00),<br>
+       _INIT_CMD(0x00, 0xC9, 0x00),<br>
+       _INIT_CMD(0x00, 0xD2, 0x04),<br>
+       _INIT_CMD(0x00, 0xD3, 0x04),<br>
+       _INIT_CMD(0x00, 0xE6, 0x03),<br>
+       _INIT_CMD(0x00, 0xE7, 0x03),<br>
+       _INIT_CMD(0x00, 0xC4, 0x08),<br>
+       _INIT_CMD(0x00, 0xC5, 0x08),<br>
+       _INIT_CMD(0x00, 0xD8, 0x07),<br>
+       _INIT_CMD(0x00, 0xD9, 0x07),<br>
+       _INIT_CMD(0x00, 0xC2, 0x06),<br>
+       _INIT_CMD(0x00, 0xC3, 0x06),<br>
+       _INIT_CMD(0x00, 0xD6, 0x05),<br>
+       _INIT_CMD(0x00, 0xD7, 0x05),<br>
+       _INIT_CMD(0x00, 0xC0, 0x0C),<br>
+       _INIT_CMD(0x00, 0xC1, 0x0C),<br>
+       _INIT_CMD(0x00, 0xD4, 0x0B),<br>
+       _INIT_CMD(0x00, 0xD5, 0x0B),<br>
+       _INIT_CMD(0x00, 0xCA, 0x0A),<br>
+       _INIT_CMD(0x00, 0xCB, 0x0A),<br>
+       _INIT_CMD(0x00, 0xDE, 0x09),<br>
+       _INIT_CMD(0x00, 0xDF, 0x09),<br>
+       _INIT_CMD(0x00, 0xC6, 0x26),<br>
+       _INIT_CMD(0x00, 0xC7, 0x26),<br>
+       _INIT_CMD(0x00, 0xCE, 0x00),<br>
+       _INIT_CMD(0x00, 0xCF, 0x00),<br>
+       _INIT_CMD(0x00, 0xDA, 0x26),<br>
+       _INIT_CMD(0x00, 0xDB, 0x26),<br>
+       _INIT_CMD(0x00, 0xE2, 0x00),<br>
+       _INIT_CMD(0x00, 0xE3, 0x00),<br>
+       _INIT_CMD(0x00, 0xB0, 0x02),<br>
+       _INIT_CMD(0x00, 0xC0, 0x00),<br>
+       _INIT_CMD(0x00, 0xC1, 0x07),<br>
+       _INIT_CMD(0x00, 0xC2, 0x0D),<br>
+       _INIT_CMD(0x00, 0xC3, 0x18),<br>
+       _INIT_CMD(0x00, 0xC4, 0x27),<br>
+       _INIT_CMD(0x00, 0xC5, 0x28),<br>
+       _INIT_CMD(0x00, 0xC6, 0x30),<br>
+       _INIT_CMD(0x00, 0xC7, 0x2E),<br>
+       _INIT_CMD(0x00, 0xC8, 0x2F),<br>
+       _INIT_CMD(0x00, 0xC9, 0x1A),<br>
+       _INIT_CMD(0x00, 0xCA, 0x20),<br>
+       _INIT_CMD(0x00, 0xCB, 0x29),<br>
+       _INIT_CMD(0x00, 0xCC, 0x26),<br>
+       _INIT_CMD(0x00, 0xCD, 0x32),<br>
+       _INIT_CMD(0x00, 0xCE, 0x33),<br>
+       _INIT_CMD(0x00, 0xCF, 0x31),<br>
+       _INIT_CMD(0x00, 0xD0, 0x06),<br>
+       _INIT_CMD(0x00, 0xD2, 0x00),<br>
+       _INIT_CMD(0x00, 0xD3, 0x07),<br>
+       _INIT_CMD(0x00, 0xD4, 0x12),<br>
+       _INIT_CMD(0x00, 0xD5, 0x26),<br>
+       _INIT_CMD(0x00, 0xD6, 0x3D),<br>
+       _INIT_CMD(0x00, 0xD7, 0x3F),<br>
+       _INIT_CMD(0x00, 0xD8, 0x3F),<br>
+       _INIT_CMD(0x00, 0xD9, 0x3F),<br>
+       _INIT_CMD(0x00, 0xDA, 0x3F),<br>
+       _INIT_CMD(0x00, 0xDB, 0x3F),<br>
+       _INIT_CMD(0x00, 0xDC, 0x3F),<br>
+       _INIT_CMD(0x00, 0xDD, 0x3F),<br>
+       _INIT_CMD(0x00, 0xDE, 0x3F),<br>
+       _INIT_CMD(0x00, 0xDF, 0x3A),<br>
+       _INIT_CMD(0x00, 0xE0, 0x37),<br>
+       _INIT_CMD(0x00, 0xE1, 0x35),<br>
+       _INIT_CMD(0x00, 0xE2, 0x07),<br>
+       _INIT_CMD(0x00, 0xB0, 0x03),<br>
+       _INIT_CMD(0x00, 0xC8, 0x0B),<br>
+       _INIT_CMD(0x00, 0xC9, 0x07),<br>
+       _INIT_CMD(0x00, 0xC3, 0x00),<br>
+       _INIT_CMD(0x00, 0xE7, 0x00),<br>
+       _INIT_CMD(0x00, 0xC5, 0x2A),<br>
+       _INIT_CMD(0x00, 0xDE, 0x2A),<br>
+       _INIT_CMD(0x00, 0xCA, 0x43),<br>
+       _INIT_CMD(0x00, 0xC9, 0x07),<br>
+       _INIT_CMD(0x00, 0xE4, 0xC0),<br>
+       _INIT_CMD(0x00, 0xE5, 0x0D),<br>
+       _INIT_CMD(0x00, 0xCB, 0x00),<br>
+       _INIT_CMD(0x00, 0xB0, 0x06),<br>
+       _INIT_CMD(0x00, 0xB8, 0xA5),<br>
+       _INIT_CMD(0x00, 0xC0, 0xA5),<br>
+       _INIT_CMD(0x00, 0xC7, 0x0F),<br>
+       _INIT_CMD(0x00, 0xD5, 0x32),<br>
+       _INIT_CMD(0x00, 0xB8, 0x00),<br>
+       _INIT_CMD(0x00, 0xC0, 0x00),<br>
+       _INIT_CMD(0x00, 0xBC, 0x00),<br>
+       _INIT_CMD(0x00, 0xB0, 0x07),<br>
+       _INIT_CMD(0x00, 0xB1, 0x00),<br>
+       _INIT_CMD(0x00, 0xB2, 0x09),<br>
+       _INIT_CMD(0x00, 0xB3, 0x19),<br>
+       _INIT_CMD(0x00, 0xB4, 0x2F),<br>
+       _INIT_CMD(0x00, 0xB5, 0x44),<br>
+       _INIT_CMD(0x00, 0xB6, 0x52),<br>
+       _INIT_CMD(0x00, 0xB7, 0x6A),<br>
+       _INIT_CMD(0x00, 0xB8, 0x8A),<br>
+       _INIT_CMD(0x00, 0xB9, 0xCA),<br>
+       _INIT_CMD(0x00, 0xBA, 0x0C),<br>
+       _INIT_CMD(0x00, 0xBB, 0x87),<br>
+       _INIT_CMD(0x00, 0xBC, 0x06),<br>
+       _INIT_CMD(0x00, 0xBD, 0x0A),<br>
+       _INIT_CMD(0x00, 0xBE, 0x9B),<br>
+       _INIT_CMD(0x00, 0xBF, 0x0C),<br>
+       _INIT_CMD(0x00, 0xC0, 0x3D),<br>
+       _INIT_CMD(0x00, 0xC1, 0x71),<br>
+       _INIT_CMD(0x00, 0xC2, 0x90),<br>
+       _INIT_CMD(0x00, 0xC3, 0xA0),<br>
+       _INIT_CMD(0x00, 0xC4, 0xA8),<br>
+       _INIT_CMD(0x00, 0xC5, 0xB1),<br>
+       _INIT_CMD(0x00, 0xC6, 0xBB),<br>
+       _INIT_CMD(0x00, 0xC7, 0xC0),<br>
+       _INIT_CMD(0x00, 0xC8, 0xC4),<br>
+       _INIT_CMD(0x00, 0xC9, 0x00),<br>
+       _INIT_CMD(0x00, 0xCA, 0x00),<br>
+       _INIT_CMD(0x00, 0xCB, 0x16),<br>
+       _INIT_CMD(0x00, 0xCC, 0xAF),<br>
+       _INIT_CMD(0x00, 0xCD, 0xFF),<br>
+       _INIT_CMD(0x00, 0xCE, 0xFF),<br>
+       _INIT_CMD(0x00, 0xB0, 0x08),<br>
+       _INIT_CMD(0x00, 0xB1, 0x04),<br>
+       _INIT_CMD(0x00, 0xB2, 0x08),<br>
+       _INIT_CMD(0x00, 0xB3, 0x19),<br>
+       _INIT_CMD(0x00, 0xB4, 0x31),<br>
+       _INIT_CMD(0x00, 0xB5, 0x46),<br>
+       _INIT_CMD(0x00, 0xB6, 0x55),<br>
+       _INIT_CMD(0x00, 0xB7, 0x6E),<br>
+       _INIT_CMD(0x00, 0xB8, 0x92),<br>
+       _INIT_CMD(0x00, 0xB9, 0xD4),<br>
+       _INIT_CMD(0x00, 0xBA, 0x1B),<br>
+       _INIT_CMD(0x00, 0xBB, 0x9B),<br>
+       _INIT_CMD(0x00, 0xBC, 0x28),<br>
+       _INIT_CMD(0x00, 0xBD, 0x2D),<br>
+       _INIT_CMD(0x00, 0xBE, 0xC3),<br>
+       _INIT_CMD(0x00, 0xBF, 0x2F),<br>
+       _INIT_CMD(0x00, 0xC0, 0x62),<br>
+       _INIT_CMD(0x00, 0xC1, 0x99),<br>
+       _INIT_CMD(0x00, 0xC2, 0xAB),<br>
+       _INIT_CMD(0x00, 0xC3, 0xBF),<br>
+       _INIT_CMD(0x00, 0xC4, 0xCF),<br>
+       _INIT_CMD(0x00, 0xC5, 0xDF),<br>
+       _INIT_CMD(0x00, 0xC6, 0xF0),<br>
+       _INIT_CMD(0x00, 0xC7, 0xF9),<br>
+       _INIT_CMD(0x00, 0xC8, 0xFC),<br>
+       _INIT_CMD(0x00, 0xC9, 0x00),<br>
+       _INIT_CMD(0x00, 0xCA, 0x00),<br>
+       _INIT_CMD(0x00, 0xCB, 0x16),<br>
+       _INIT_CMD(0x00, 0xCC, 0xAF),<br>
+       _INIT_CMD(0x00, 0xCD, 0xFF),<br>
+       _INIT_CMD(0x00, 0xCE, 0xFF),<br>
+       _INIT_CMD(0x00, 0xB0, 0x09),<br>
+       _INIT_CMD(0x00, 0xB1, 0x04),<br>
+       _INIT_CMD(0x00, 0xB2, 0x05),<br>
+       _INIT_CMD(0x00, 0xB3, 0x17),<br>
+       _INIT_CMD(0x00, 0xB4, 0x2E),<br>
+       _INIT_CMD(0x00, 0xB5, 0x42),<br>
+       _INIT_CMD(0x00, 0xB6, 0x51),<br>
+       _INIT_CMD(0x00, 0xB7, 0x69),<br>
+       _INIT_CMD(0x00, 0xB8, 0x88),<br>
+       _INIT_CMD(0x00, 0xB9, 0xC9),<br>
+       _INIT_CMD(0x00, 0xBA, 0x0C),<br>
+       _INIT_CMD(0x00, 0xBB, 0x86),<br>
+       _INIT_CMD(0x00, 0xBC, 0x03),<br>
+       _INIT_CMD(0x00, 0xBD, 0x08),<br>
+       _INIT_CMD(0x00, 0xBE, 0x95),<br>
+       _INIT_CMD(0x00, 0xBF, 0x05),<br>
+       _INIT_CMD(0x00, 0xC0, 0x35),<br>
+       _INIT_CMD(0x00, 0xC1, 0x62),<br>
+       _INIT_CMD(0x00, 0xC2, 0x81),<br>
+       _INIT_CMD(0x00, 0xC3, 0x96),<br>
+       _INIT_CMD(0x00, 0xC4, 0x9E),<br>
+       _INIT_CMD(0x00, 0xC5, 0xA5),<br>
+       _INIT_CMD(0x00, 0xC6, 0xAD),<br>
+       _INIT_CMD(0x00, 0xC7, 0xB1),<br>
+       _INIT_CMD(0x00, 0xC8, 0xB4),<br>
+       _INIT_CMD(0x00, 0xC9, 0x00),<br>
+       _INIT_CMD(0x00, 0xCA, 0x00),<br>
+       _INIT_CMD(0x00, 0xCB, 0x16),<br>
+       _INIT_CMD(0x00, 0xCC, 0xAF),<br>
+       _INIT_CMD(0x00, 0xCD, 0xFF),<br>
+       _INIT_CMD(0x00, 0xCE, 0xFF),<br>
+       _INIT_CMD(0x00, 0xB0, 0x0A),<br>
+       _INIT_CMD(0x00, 0xB1, 0x00),<br>
+       _INIT_CMD(0x00, 0xB2, 0x09),<br>
+       _INIT_CMD(0x00, 0xB3, 0x19),<br>
+       _INIT_CMD(0x00, 0xB4, 0x2F),<br>
+       _INIT_CMD(0x00, 0xB5, 0x44),<br>
+       _INIT_CMD(0x00, 0xB6, 0x52),<br>
+       _INIT_CMD(0x00, 0xB7, 0x6A),<br>
+       _INIT_CMD(0x00, 0xB8, 0x8A),<br>
+       _INIT_CMD(0x00, 0xB9, 0xCA),<br>
+       _INIT_CMD(0x00, 0xBA, 0x0C),<br>
+       _INIT_CMD(0x00, 0xBB, 0x87),<br>
+       _INIT_CMD(0x00, 0xBC, 0x06),<br>
+       _INIT_CMD(0x00, 0xBD, 0x0A),<br>
+       _INIT_CMD(0x00, 0xBE, 0x9B),<br>
+       _INIT_CMD(0x00, 0xBF, 0x0C),<br>
+       _INIT_CMD(0x00, 0xC0, 0x3D),<br>
+       _INIT_CMD(0x00, 0xC1, 0x71),<br>
+       _INIT_CMD(0x00, 0xC2, 0x90),<br>
+       _INIT_CMD(0x00, 0xC3, 0xA0),<br>
+       _INIT_CMD(0x00, 0xC4, 0xA8),<br>
+       _INIT_CMD(0x00, 0xC5, 0xB1),<br>
+       _INIT_CMD(0x00, 0xC6, 0xBB),<br>
+       _INIT_CMD(0x00, 0xC7, 0xC0),<br>
+       _INIT_CMD(0x00, 0xC8, 0xC4),<br>
+       _INIT_CMD(0x00, 0xC9, 0x00),<br>
+       _INIT_CMD(0x00, 0xCA, 0x00),<br>
+       _INIT_CMD(0x00, 0xCB, 0x16),<br>
+       _INIT_CMD(0x00, 0xCC, 0xAF),<br>
+       _INIT_CMD(0x00, 0xCD, 0xFF),<br>
+       _INIT_CMD(0x00, 0xCE, 0xFF),<br>
+       _INIT_CMD(0x00, 0xB0, 0x0B),<br>
+       _INIT_CMD(0x00, 0xB1, 0x04),<br>
+       _INIT_CMD(0x00, 0xB2, 0x08),<br>
+       _INIT_CMD(0x00, 0xB3, 0x19),<br>
+       _INIT_CMD(0x00, 0xB4, 0x31),<br>
+       _INIT_CMD(0x00, 0xB5, 0x46),<br>
+       _INIT_CMD(0x00, 0xB6, 0x55),<br>
+       _INIT_CMD(0x00, 0xB7, 0x6E),<br>
+       _INIT_CMD(0x00, 0xB8, 0x92),<br>
+       _INIT_CMD(0x00, 0xB9, 0xD4),<br>
+       _INIT_CMD(0x00, 0xBA, 0x1B),<br>
+       _INIT_CMD(0x00, 0xBB, 0x9B),<br>
+       _INIT_CMD(0x00, 0xBC, 0x28),<br>
+       _INIT_CMD(0x00, 0xBD, 0x2D),<br>
+       _INIT_CMD(0x00, 0xBE, 0xC3),<br>
+       _INIT_CMD(0x00, 0xBF, 0x2F),<br>
+       _INIT_CMD(0x00, 0xC0, 0x62),<br>
+       _INIT_CMD(0x00, 0xC1, 0x99),<br>
+       _INIT_CMD(0x00, 0xC2, 0xAB),<br>
+       _INIT_CMD(0x00, 0xC3, 0xBF),<br>
+       _INIT_CMD(0x00, 0xC4, 0xCF),<br>
+       _INIT_CMD(0x00, 0xC5, 0xDF),<br>
+       _INIT_CMD(0x00, 0xC6, 0xF0),<br>
+       _INIT_CMD(0x00, 0xC7, 0xF9),<br>
+       _INIT_CMD(0x00, 0xC8, 0xFC),<br>
+       _INIT_CMD(0x00, 0xC9, 0x00),<br>
+       _INIT_CMD(0x00, 0xCA, 0x00),<br>
+       _INIT_CMD(0x00, 0xCB, 0x16),<br>
+       _INIT_CMD(0x00, 0xCC, 0xAF),<br>
+       _INIT_CMD(0x00, 0xCD, 0xFF),<br>
+       _INIT_CMD(0x00, 0xCE, 0xFF),<br>
+       _INIT_CMD(0x00, 0xB0, 0x0C),<br>
+       _INIT_CMD(0x00, 0xB1, 0x04),<br>
+       _INIT_CMD(0x00, 0xB2, 0x05),<br>
+       _INIT_CMD(0x00, 0xB3, 0x17),<br>
+       _INIT_CMD(0x00, 0xB4, 0x2E),<br>
+       _INIT_CMD(0x00, 0xB5, 0x42),<br>
+       _INIT_CMD(0x00, 0xB6, 0x51),<br>
+       _INIT_CMD(0x00, 0xB7, 0x69),<br>
+       _INIT_CMD(0x00, 0xB8, 0x88),<br>
+       _INIT_CMD(0x00, 0xB9, 0xC9),<br>
+       _INIT_CMD(0x00, 0xBA, 0x0C),<br>
+       _INIT_CMD(0x00, 0xBB, 0x86),<br>
+       _INIT_CMD(0x00, 0xBC, 0x03),<br>
+       _INIT_CMD(0x00, 0xBD, 0x08),<br>
+       _INIT_CMD(0x00, 0xBE, 0x95),<br>
+       _INIT_CMD(0x00, 0xBF, 0x05),<br>
+       _INIT_CMD(0x00, 0xC0, 0x35),<br>
+       _INIT_CMD(0x00, 0xC1, 0x62),<br>
+       _INIT_CMD(0x00, 0xC2, 0x81),<br>
+       _INIT_CMD(0x00, 0xC3, 0x96),<br>
+       _INIT_CMD(0x00, 0xC4, 0x9E),<br>
+       _INIT_CMD(0x00, 0xC5, 0xA5),<br>
+       _INIT_CMD(0x00, 0xC6, 0xAD),<br>
+       _INIT_CMD(0x00, 0xC7, 0xB1),<br>
+       _INIT_CMD(0x00, 0xC8, 0xB4),<br>
+       _INIT_CMD(0x00, 0xC9, 0x00),<br>
+       _INIT_CMD(0x00, 0xCA, 0x00),<br>
+       _INIT_CMD(0x00, 0xCB, 0x16),<br>
+       _INIT_CMD(0x00, 0xCC, 0xAF),<br>
+       _INIT_CMD(0x00, 0xCD, 0xFF),<br>
+       _INIT_CMD(0x00, 0xCE, 0xFF),<br>
+       _INIT_CMD(0x00, 0xB0, 0x00),<br>
+       _INIT_CMD(0x00, 0xB3, 0x08),<br>
+       _INIT_CMD(0x00, 0xB0, 0x04),<br>
+       _INIT_CMD(0x64, 0xB8, 0x68),<br>
+<br>
+       {},<br>
+};<br>
+<br>
+static const struct panel_desc boe_himax8279d10p_panel_desc = {<br>
+       .display_mode = &amp;default_display_mode,<br>
+       .bpc = 8,<br>
+       .width_mm = 135,<br>
+       .height_mm = 216,<br>
+       .delay_t1 = 5000,<br>
+       .reset_delay_t2 = 14000,<br>
+       .reset_delay_t3 = 1000,<br>
+       .reset_delay_t4 = 1000,<br>
+       .reset_delay_t5 = 5000,<br>
+       .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |<br>
+                       MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,<br>
+       .format = MIPI_DSI_FMT_RGB888,<br>
+       .lanes = 4,<br>
+       .on_cmds = boe_himax8279d10p_on_cmds,<br>
+       .off_cmds = default_off_cmds,<br>
+};<br>
+<br>
+static const struct of_device_id panel_of_match[] = {<br>
+       { .compatible = &quot;boe,himax8279d8p&quot;,<br>
+         .data = &amp;boe_himax8279d8p_panel_desc<br>
+       }, { .compatible = &quot;boe,himax8279d10p&quot;,<br>
+         .data = &amp;boe_himax8279d10p_panel_desc<br>
+       }, {<br>
+               /* sentinel */<br>
+       }<br>
+};<br>
+MODULE_DEVICE_TABLE(of, panel_of_match);<br>
+<br>
+static int panel_add(struct panel_info *pinfo)<br>
+{<br>
+       struct device *dev = &amp;pinfo-&gt;link-&gt;dev;<br>
+       int ret;<br>
+<br>
+       pinfo-&gt;pp18_gpio = devm_gpiod_get_optional(dev, &quot;pp18&quot;, GPIOD_OUT_HIGH);<br>
+       if (IS_ERR(pinfo-&gt;pp18_gpio)) {<br>
+               ret = PTR_ERR(pinfo-&gt;pp18_gpio);<br>
+               if (ret != -EPROBE_DEFER)<br>
+                       DRM_DEV_ERROR(dev, &quot;failed to get pp18 gpio: %d\n&quot;,<br>
+                                       ret);<br>
+               return ret;<br>
+       }<br>
+<br>
+       pinfo-&gt;pp33_gpio = devm_gpiod_get_optional(dev, &quot;pp33&quot;, GPIOD_OUT_HIGH);<br>
+       if (IS_ERR(pinfo-&gt;pp33_gpio)) {<br>
+               ret = PTR_ERR(pinfo-&gt;pp33_gpio);<br>
+               if (ret != -EPROBE_DEFER)<br>
+                       DRM_DEV_ERROR(dev, &quot;failed to get pp33 gpio: %d\n&quot;,<br>
+                                       ret);<br>
+               return ret;<br>
+       }<br>
+<br>
+       pinfo-&gt;enable_gpio = devm_gpiod_get_optional(dev, &quot;enable&quot;,<br>
+                                                       GPIOD_OUT_HIGH);<br>
+       if (IS_ERR(pinfo-&gt;enable_gpio)) {<br>
+               ret = PTR_ERR(pinfo-&gt;enable_gpio);<br>
+               if (ret != -EPROBE_DEFER)<br>
+                       DRM_DEV_ERROR(dev, &quot;failed to get enable gpio: %d\n&quot;,<br>
+                                       ret);<br>
+               return ret;<br>
+       }<br>
+<br>
+       pinfo-&gt;backlight = devm_of_find_backlight(dev);<br>
+       if (IS_ERR(pinfo-&gt;backlight))<br>
+               return PTR_ERR(pinfo-&gt;backlight);<br>
+<br>
+       drm_panel_init(&amp;pinfo-&gt;base);<br>
+       pinfo-&gt;base.funcs = &amp;panel_funcs;<br>
+       pinfo-&gt;<a href="http://base.dev" rel="noreferrer" target="_blank">base.dev</a> = &amp;pinfo-&gt;link-&gt;dev;<br>
+<br>
+       ret = drm_panel_add(&amp;pinfo-&gt;base);<br>
+       if (ret &lt; 0)<br>
+               return ret;<br>
+<br>
+       return 0;<br>
+}<br>
+<br>
+static void panel_del(struct panel_info *pinfo)<br>
+{<br>
+       if (pinfo-&gt;<a href="http://base.dev" rel="noreferrer" target="_blank">base.dev</a>)<br>
+               drm_panel_remove(&amp;pinfo-&gt;base);<br>
+}<br>
+<br>
+static int panel_probe(struct mipi_dsi_device *dsi)<br>
+{<br>
+       struct panel_info *pinfo;<br>
+       const struct panel_desc *desc;<br>
+       int err;<br>
+<br>
+       pinfo = devm_kzalloc(&amp;dsi-&gt;dev, sizeof(*pinfo), GFP_KERNEL);<br>
+       if (!pinfo)<br>
+               return -ENOMEM;<br>
+<br>
+       desc = of_device_get_match_data(&amp;dsi-&gt;dev);<br>
+       dsi-&gt;mode_flags = desc-&gt;mode_flags;<br>
+       dsi-&gt;format = desc-&gt;format;<br>
+       dsi-&gt;lanes = desc-&gt;lanes;<br>
+       pinfo-&gt;desc = desc;<br>
+<br>
+       pinfo-&gt;link = dsi;<br>
+       mipi_dsi_set_drvdata(dsi, pinfo);<br>
+<br>
+       err = panel_add(pinfo);<br>
+       if (err &lt; 0)<br>
+               return err;<br>
+<br>
+       return mipi_dsi_attach(dsi);<br>
+}<br>
+<br>
+static int panel_remove(struct mipi_dsi_device *dsi)<br>
+{<br>
+       struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);<br>
+       int err;<br>
+<br>
+       err = boe_panel_unprepare(&amp;pinfo-&gt;base);<br>
+       if (err &lt; 0)<br>
+               DRM_DEV_ERROR(&amp;dsi-&gt;dev, &quot;failed to unprepare panel: %d\n&quot;,<br>
+                               err);<br>
+<br>
+       err = boe_panel_disable(&amp;pinfo-&gt;base);<br>
+       if (err &lt; 0)<br>
+               DRM_DEV_ERROR(&amp;dsi-&gt;dev, &quot;failed to disable panel: %d\n&quot;, err);<br>
+<br>
+       err = mipi_dsi_detach(dsi);<br>
+       if (err &lt; 0)<br>
+               DRM_DEV_ERROR(&amp;dsi-&gt;dev, &quot;failed to detach from DSI host: %d\n&quot;,<br>
+                               err);<br>
+<br>
+       drm_panel_detach(&amp;pinfo-&gt;base);<br>
+       panel_del(pinfo);<br>
+<br>
+       return 0;<br>
+}<br>
+<br>
+static void panel_shutdown(struct mipi_dsi_device *dsi)<br>
+{<br>
+       struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);<br>
+<br>
+       boe_panel_disable(&amp;pinfo-&gt;base);<br>
+       boe_panel_unprepare(&amp;pinfo-&gt;base);<br>
+}<br>
+<br>
+static struct mipi_dsi_driver panel_driver = {<br>
+       .driver = {<br>
+               .name = &quot;panel-boe-himax8279d&quot;,<br>
+               .of_match_table = panel_of_match,<br>
+       },<br>
+       .probe = panel_probe,<br>
+       .remove = panel_remove,<br>
+       .shutdown = panel_shutdown,<br>
+};<br>
+module_mipi_dsi_driver(panel_driver);<br>
+<br>
+MODULE_AUTHOR(&quot;Jerry Han &lt;<a href="mailto:jerry.han.hq@gmail.com" target="_blank">jerry.han.hq@gmail.com</a>&gt;&quot;);<br>
+MODULE_DESCRIPTION(&quot;Boe Himax8279d driver&quot;);<br>
+MODULE_LICENSE(&quot;GPL v2&quot;);<br>
-- <br>
2.17.1<br>
<br>
</blockquote></div>
Sam Ravnborg June 26, 2019, 12:53 p.m. UTC | #2
Hi Jerry.

On Thu, Apr 25, 2019 at 11:27:12AM +0800, Jerry Han wrote:
> Support Boe Himax8279d 8.0" 1200x1920 TFT LCD panel, it is a MIPI DSI
> panel.
> 
> 
> Signed-off-by: Jerry Han <jerry.han.hq@gmail.com>
> Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
> Reviewed-by: Derek Basehore <dbasehore@chromium.org>
> Cc: Jitao Shi <jitao.shi@mediatek.com>
> Cc: Rock wang <rock_wang@himax.com.cn>
> ---
>  MAINTAINERS                                  |    6 +
>  drivers/gpu/drm/panel/Kconfig                |   11 +
>  drivers/gpu/drm/panel/Makefile               |    1 +
>  drivers/gpu/drm/panel/panel-boe-himax8279d.c | 1050 ++++++++++++++++++
>  4 files changed, 1068 insertions(+)
>  create mode 100644 drivers/gpu/drm/panel/panel-boe-himax8279d.c

When applying this patch I got the following warnings.
Please fix them, and double check that checkpatch is happy.
(Some warnings can be safely ignored but trivial ones like these needs
fixing).

	Sam

-:211: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#211: FILE: drivers/gpu/drm/panel/panel-boe-himax8279d.c:95:
+			err = mipi_dsi_dcs_write(pinfo->link,
+						    cmd->data[1], NULL, 0);

-:214: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#214: FILE: drivers/gpu/drm/panel/panel-boe-himax8279d.c:98:
+			err = mipi_dsi_dcs_write(pinfo->link,
+						    cmd->data[1], cmd->data + 2,

-:221: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#221: FILE: drivers/gpu/drm/panel/panel-boe-himax8279d.c:105:
+		usleep_range((cmd->data[0]) * 1000,
+			    (1 + cmd->data[0]) * 1000);

-:250: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#250: FILE: drivers/gpu/drm/panel/panel-boe-himax8279d.c:134:
+		DRM_DEV_ERROR(panel->dev,
+				"failed to send DCS Off Code: %d\n", err);

-:295: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#295: FILE: drivers/gpu/drm/panel/panel-boe-himax8279d.c:179:
+		DRM_DEV_ERROR(panel->dev,
+				"failed to send DCS Init Code: %d\n", err);

-:319: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#319: FILE: drivers/gpu/drm/panel/panel-boe-himax8279d.c:203:
+		DRM_DEV_ERROR(panel->drm->dev,
+				"Failed to enable backlight %d\n", ret);

-:337: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#337: FILE: drivers/gpu/drm/panel/panel-boe-himax8279d.c:221:
+		DRM_DEV_ERROR(panel->drm->dev, "failed to add mode %ux%u@%u\n",
+				m->hdisplay, m->vdisplay, m->vrefresh);

-:1050: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1050: FILE: drivers/gpu/drm/panel/panel-boe-himax8279d.c:934:
+			DRM_DEV_ERROR(dev, "failed to get pp18 gpio: %d\n",
+					ret);

-:1059: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1059: FILE: drivers/gpu/drm/panel/panel-boe-himax8279d.c:943:
+			DRM_DEV_ERROR(dev, "failed to get pp33 gpio: %d\n",
+					ret);

-:1064: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1064: FILE: drivers/gpu/drm/panel/panel-boe-himax8279d.c:948:
+	pinfo->enable_gpio = devm_gpiod_get_optional(dev, "enable",
+							GPIOD_OUT_HIGH);

-:1069: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1069: FILE: drivers/gpu/drm/panel/panel-boe-himax8279d.c:953:
+			DRM_DEV_ERROR(dev, "failed to get enable gpio: %d\n",
+					ret);

-:1128: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1128: FILE: drivers/gpu/drm/panel/panel-boe-himax8279d.c:1012:
+		DRM_DEV_ERROR(&dsi->dev, "failed to unprepare panel: %d\n",
+				err);

-:1137: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#1137: FILE: drivers/gpu/drm/panel/panel-boe-himax8279d.c:1021:
+		DRM_DEV_ERROR(&dsi->dev, "failed to detach from DSI host: %d\n",
+				err);
Emil Velikov July 1, 2019, 1:42 p.m. UTC | #3
Hi Jerry,

On Thu, 25 Apr 2019 at 08:40, Jerry Han <jerry.han.hq@gmail.com> wrote:
>
> Support Boe Himax8279d 8.0" 1200x1920 TFT LCD panel, it is a MIPI DSI
> panel.
>
> V8:
> - Modify communication address
>
> V7:
> - Add the information of the reviewer
> - Remove unnecessary delays, The udelay_range code gracefully returns
>     without hitting the scheduler on a delay of 0. (Derek)
> - Merge the same data structures, like display_mode and off_cmds (Derek)
> - Optimize the processing of results returned by
>     devm_gpiod_get_optional (Derek)
>
> V6:
> - Add the information of the reviewer (Sam)
> - Delete unnecessary header files #include <linux/fb.h> (Sam)
> - The config DRM_PANEL_BOE_HIMAX8279D appears twice. Drop one of them (Sam)
> - ADD static, set_gpios function is not used outside this module (Sam)
>
> V5:
> - Added changelog
>
> V4:
> - Frefix all function maes with boe_ (Sam)
> - Fsed "enable_gpio" replace "reset_gpio", Make it look clearer (Sam)
> - Sort include lines alphabetically (Sam)
> - Fixed entries in the makefile must be sorted alphabetically (Sam)
> - Add send_mipi_cmds function to avoid duplicating the code (Sam)
> - Add the necessary delay(reset_delay_t5) between reset and sending
>     the initialization command (Rock wang)
>
> V3:
> - Remove unnecessary delays in sending initialization commands (Jitao Shi)
>
> V2:
> - Use SPDX identifier (Sam)
> - Use necessary header files replace drmP.h (Sam)
> - Delete unnecessary header files #include <linux/err.h> (Sam)
> - Specifies a GPIOs array to control the reset timing,
>     instead of reading "dsi-reset-sequence" data from DTS (Sam)
> - Delete backlight_disable() function when already disabled (Sam)
> - Use devm_of_find_backlight() replace of_find_backlight_by_node() (Sam)
> - Move the necessary data in the DTS to the current file,
>     like porch, display_mode and Init code etc. (Sam)
> - Add compatible device "boe,himax8279d10p" (Sam)
>
> Signed-off-by: Jerry Han <jerry.han.hq@gmail.com>
> Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
> Reviewed-by: Derek Basehore <dbasehore@chromium.org>
> Cc: Jitao Shi <jitao.shi@mediatek.com>
> Cc: Rock wang <rock_wang@himax.com.cn>
> ---
While the DT has landed, this patch is not merged it seems.
I think that Sam is waiting for a version which does not trigger so
many check-patch warnings.

That said, a couple of comments if I may.

> +       struct gpio_desc *enable_gpio;
> +       struct gpio_desc *pp33_gpio;
> +       struct gpio_desc *pp18_gpio;
DT claims that these gpios are required, yet one is using the optional gpio API.
Is the code off, or does the DT need fixing?


> +static int send_mipi_cmds(struct drm_panel *panel, const struct panel_cmd *cmds)
> +{
> +       struct panel_info *pinfo = to_panel_info(panel);
> +       unsigned int i = 0;
> +       int err;
> +
> +       if (!cmds)
> +               return -EFAULT;
> +
> +       for (i = 0; cmds[i].len != 0; i++) {
> +               const struct panel_cmd *cmd = &cmds[i];
> +
> +               if (cmd->len == 2)
> +                       err = mipi_dsi_dcs_write(pinfo->link,
> +                                                   cmd->data[1], NULL, 0);
> +               else
> +                       err = mipi_dsi_dcs_write(pinfo->link,
> +                                                   cmd->data[1], cmd->data + 2,
> +                                                   cmd->len - 2);
> +
> +               if (err < 0)
> +                       return err;
> +
> +               usleep_range((cmd->data[0]) * 1000,
> +                           (1 + cmd->data[0]) * 1000);
> +       }
> +
This format seems semi-magical. Any particular reason why you're not
using the helpers?
In particular, enter/exit sleep mode and set display on/off.

Speaking of which - the 8inch display uses then, yet they are missing
for the 10inch one. Seems like there's a bug in there.

Plus we have some repeating patterns in the vendor/undocumented
commands - good reason to get those into separate hunks.
With the above in place, you can effectively drop the .off_cmd
callback and sleep field from the INIT_CMD arrays.

Hence, less code to debug and maintain ;-)

HTH
Emil
Jerry Han July 26, 2019, 3:57 a.m. UTC | #4
Hi Emil Velikov:

First of all, thank you for your comments.

> +       struct gpio_desc *enable_gpio;
> +       struct gpio_desc *pp33_gpio;
> +       struct gpio_desc *pp18_gpio;
DT claims that these gpios are required, yet one is using the optional gpio
API.
Is the code off, or does the DT need fixing?

Thank you for your advice , I will  fix code.

static int send_mipi_cmds(struct drm_panel *panel, const struct panel_cmd
*cmds)
This format seems semi-magical. Any particular reason why you're not
using the helpers?
In particular, enter/exit sleep mode and set display on/off.

Normally, we only need to download 0x28 0x10 commands to power-key down.
I noticed that helper func (mipi_dsi_dcs_set_display_off,
mipi_dsi_dcs_enter_sleep_mode) help me send this commands(0x28 0x10).

But based on previous debugging experience, Some vendors are special and
may send other commands after sending cmd 0x28 0x10 or before send cmd 0x28
0x10.
this problem may also occur in our vendor,
so i think this above approach helps me manage code better.

Thanks.


Emil Velikov <emil.l.velikov@gmail.com> 于2019年7月1日周一 下午9:41写道:

> Hi Jerry,
>
> On Thu, 25 Apr 2019 at 08:40, Jerry Han <jerry.han.hq@gmail.com> wrote:
> >
> > Support Boe Himax8279d 8.0" 1200x1920 TFT LCD panel, it is a MIPI DSI
> > panel.
> >
> > V8:
> > - Modify communication address
> >
> > V7:
> > - Add the information of the reviewer
> > - Remove unnecessary delays, The udelay_range code gracefully returns
> >     without hitting the scheduler on a delay of 0. (Derek)
> > - Merge the same data structures, like display_mode and off_cmds (Derek)
> > - Optimize the processing of results returned by
> >     devm_gpiod_get_optional (Derek)
> >
> > V6:
> > - Add the information of the reviewer (Sam)
> > - Delete unnecessary header files #include <linux/fb.h> (Sam)
> > - The config DRM_PANEL_BOE_HIMAX8279D appears twice. Drop one of them
> (Sam)
> > - ADD static, set_gpios function is not used outside this module (Sam)
> >
> > V5:
> > - Added changelog
> >
> > V4:
> > - Frefix all function maes with boe_ (Sam)
> > - Fsed "enable_gpio" replace "reset_gpio", Make it look clearer (Sam)
> > - Sort include lines alphabetically (Sam)
> > - Fixed entries in the makefile must be sorted alphabetically (Sam)
> > - Add send_mipi_cmds function to avoid duplicating the code (Sam)
> > - Add the necessary delay(reset_delay_t5) between reset and sending
> >     the initialization command (Rock wang)
> >
> > V3:
> > - Remove unnecessary delays in sending initialization commands (Jitao
> Shi)
> >
> > V2:
> > - Use SPDX identifier (Sam)
> > - Use necessary header files replace drmP.h (Sam)
> > - Delete unnecessary header files #include <linux/err.h> (Sam)
> > - Specifies a GPIOs array to control the reset timing,
> >     instead of reading "dsi-reset-sequence" data from DTS (Sam)
> > - Delete backlight_disable() function when already disabled (Sam)
> > - Use devm_of_find_backlight() replace of_find_backlight_by_node() (Sam)
> > - Move the necessary data in the DTS to the current file,
> >     like porch, display_mode and Init code etc. (Sam)
> > - Add compatible device "boe,himax8279d10p" (Sam)
> >
> > Signed-off-by: Jerry Han <jerry.han.hq@gmail.com>
> > Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
> > Reviewed-by: Derek Basehore <dbasehore@chromium.org>
> > Cc: Jitao Shi <jitao.shi@mediatek.com>
> > Cc: Rock wang <rock_wang@himax.com.cn>
> > ---
> While the DT has landed, this patch is not merged it seems.
> I think that Sam is waiting for a version which does not trigger so
> many check-patch warnings.
>
> That said, a couple of comments if I may.
>
> > +       struct gpio_desc *enable_gpio;
> > +       struct gpio_desc *pp33_gpio;
> > +       struct gpio_desc *pp18_gpio;
> DT claims that these gpios are required, yet one is using the optional
> gpio API.
> Is the code off, or does the DT need fixing?
>
>
> > +static int send_mipi_cmds(struct drm_panel *panel, const struct
> panel_cmd *cmds)
> > +{
> > +       struct panel_info *pinfo = to_panel_info(panel);
> > +       unsigned int i = 0;
> > +       int err;
> > +
> > +       if (!cmds)
> > +               return -EFAULT;
> > +
> > +       for (i = 0; cmds[i].len != 0; i++) {
> > +               const struct panel_cmd *cmd = &cmds[i];
> > +
> > +               if (cmd->len == 2)
> > +                       err = mipi_dsi_dcs_write(pinfo->link,
> > +                                                   cmd->data[1], NULL,
> 0);
> > +               else
> > +                       err = mipi_dsi_dcs_write(pinfo->link,
> > +                                                   cmd->data[1],
> cmd->data + 2,
> > +                                                   cmd->len - 2);
> > +
> > +               if (err < 0)
> > +                       return err;
> > +
> > +               usleep_range((cmd->data[0]) * 1000,
> > +                           (1 + cmd->data[0]) * 1000);
> > +       }
> > +
> This format seems semi-magical. Any particular reason why you're not
> using the helpers?
> In particular, enter/exit sleep mode and set display on/off.
>
> Speaking of which - the 8inch display uses then, yet they are missing
> for the 10inch one. Seems like there's a bug in there.
>
> Plus we have some repeating patterns in the vendor/undocumented
> commands - good reason to get those into separate hunks.
> With the above in place, you can effectively drop the .off_cmd
> callback and sleep field from the INIT_CMD arrays.
>
> Hence, less code to debug and maintain ;-)
>
> HTH
> Emil
>
Emil Velikov July 30, 2019, 4:26 p.m. UTC | #5
Hi Jerry,

Can you please disable HTML emails for the Gmail web client and reply
inline. There are multiple articles how to do that.

On 2019/07/26, Jerry Han wrote:
> Hi Emil Velikov:
> 
> First of all, thank you for your comments.
> 
> > Hi Jerry,
> >
> > On Thu, 25 Apr 2019 at 08:40, Jerry Han <jerry.han.hq@gmail.com> wrote:
> > >
> > > Support Boe Himax8279d 8.0" 1200x1920 TFT LCD panel, it is a MIPI DSI
> > > panel.
> > >
> > > V8:
> > > - Modify communication address
> > >
> > > V7:
> > > - Add the information of the reviewer
> > > - Remove unnecessary delays, The udelay_range code gracefully returns
> > >     without hitting the scheduler on a delay of 0. (Derek)
> > > - Merge the same data structures, like display_mode and off_cmds (Derek)
> > > - Optimize the processing of results returned by
> > >     devm_gpiod_get_optional (Derek)
> > >
> > > V6:
> > > - Add the information of the reviewer (Sam)
> > > - Delete unnecessary header files #include <linux/fb.h> (Sam)
> > > - The config DRM_PANEL_BOE_HIMAX8279D appears twice. Drop one of them
> > (Sam)
> > > - ADD static, set_gpios function is not used outside this module (Sam)
> > >
> > > V5:
> > > - Added changelog
> > >
> > > V4:
> > > - Frefix all function maes with boe_ (Sam)
> > > - Fsed "enable_gpio" replace "reset_gpio", Make it look clearer (Sam)
> > > - Sort include lines alphabetically (Sam)
> > > - Fixed entries in the makefile must be sorted alphabetically (Sam)
> > > - Add send_mipi_cmds function to avoid duplicating the code (Sam)
> > > - Add the necessary delay(reset_delay_t5) between reset and sending
> > >     the initialization command (Rock wang)
> > >
> > > V3:
> > > - Remove unnecessary delays in sending initialization commands (Jitao
> > Shi)
> > >
> > > V2:
> > > - Use SPDX identifier (Sam)
> > > - Use necessary header files replace drmP.h (Sam)
> > > - Delete unnecessary header files #include <linux/err.h> (Sam)
> > > - Specifies a GPIOs array to control the reset timing,
> > >     instead of reading "dsi-reset-sequence" data from DTS (Sam)
> > > - Delete backlight_disable() function when already disabled (Sam)
> > > - Use devm_of_find_backlight() replace of_find_backlight_by_node() (Sam)
> > > - Move the necessary data in the DTS to the current file,
> > >     like porch, display_mode and Init code etc. (Sam)
> > > - Add compatible device "boe,himax8279d10p" (Sam)
> > >
> > > Signed-off-by: Jerry Han <jerry.han.hq@gmail.com>
> > > Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
> > > Reviewed-by: Derek Basehore <dbasehore@chromium.org>
> > > Cc: Jitao Shi <jitao.shi@mediatek.com>
> > > Cc: Rock wang <rock_wang@himax.com.cn>
> > > ---
> > While the DT has landed, this patch is not merged it seems.
> > I think that Sam is waiting for a version which does not trigger so
> > many check-patch warnings.
> >
> > That said, a couple of comments if I may.
> >
> > > +       struct gpio_desc *enable_gpio;
> > > +       struct gpio_desc *pp33_gpio;
> > > +       struct gpio_desc *pp18_gpio;
> > DT claims that these gpios are required, yet one is using the optional
> > gpio API.
> > Is the code off, or does the DT need fixing?
> >
> >
> Thank you for your advice , I will  fix code.
> 
> > > +static int send_mipi_cmds(struct drm_panel *panel, const struct
> > panel_cmd *cmds)
> > > +{
> > > +       struct panel_info *pinfo = to_panel_info(panel);
> > > +       unsigned int i = 0;
> > > +       int err;
> > > +
> > > +       if (!cmds)
> > > +               return -EFAULT;
> > > +
> > > +       for (i = 0; cmds[i].len != 0; i++) {
> > > +               const struct panel_cmd *cmd = &cmds[i];
> > > +
> > > +               if (cmd->len == 2)
> > > +                       err = mipi_dsi_dcs_write(pinfo->link,
> > > +                                                   cmd->data[1], NULL,
> > 0);
> > > +               else
> > > +                       err = mipi_dsi_dcs_write(pinfo->link,
> > > +                                                   cmd->data[1],
> > cmd->data + 2,
> > > +                                                   cmd->len - 2);
> > > +
> > > +               if (err < 0)
> > > +                       return err;
> > > +
> > > +               usleep_range((cmd->data[0]) * 1000,
> > > +                           (1 + cmd->data[0]) * 1000);
> > > +       }
> > > +
> > This format seems semi-magical. Any particular reason why you're not
> > using the helpers?
> > In particular, enter/exit sleep mode and set display on/off.
> >
> > Speaking of which - the 8inch display uses then, yet they are missing
> > for the 10inch one. Seems like there's a bug in there.
> >
> > Plus we have some repeating patterns in the vendor/undocumented
> > commands - good reason to get those into separate hunks.
> > With the above in place, you can effectively drop the .off_cmd
> > callback and sleep field from the INIT_CMD arrays.
> >
> > Hence, less code to debug and maintain ;-)
> >

> Normally, we only need to download 0x28 0x10 commands to power-key down.
> I noticed that helper func (mipi_dsi_dcs_set_display_off,
> mipi_dsi_dcs_enter_sleep_mode) help me send this commands(0x28 0x10).
> 
> But based on previous debugging experience, Some vendors are special and
> may send other commands after sending cmd 0x28 0x10 or before send cmd 0x28
> 0x10.
> this problem may also occur in our vendor,
> so i think this above approach helps me manage code better.
> 
Using the helpers helper does _not_ prevent you from issuing other
commands before or after them.

Looking through the existing codebase you'll see plenty of other panel
drivers doing so.

If anything you'll spot that nearly every driver calls 
mipi_dsi_dcs_set_display_{on,off} in their enable/disable callbacks.

So what I'm suggesting:
 - use the helpers in the respective callbacks:
a) display on/off for enable/disable
b) exit/enter sleep mode for prepare/unprepare
If any of these cause issues, omit them and adding an inline comment
clearly explain why they are missing.

 - add explicit delays around the helpers, if needed

 - kill off default_off_cmds and related infra

 - factor out the command stream differences, how you did in for
reset_delay*. Quck compare shows 8 differences in the 300 commands.

 - kill off the delay stored in data[0]

 - don't repeat the following sequence _12_ times
_INIT_CMD(0xB0, 0x08),
...
_INIT_CMD(0xCE, 0xFF),


With the above in place, the driver will become a lot smaller and easier
to understand.

Thanks
-Emil
Jerry Han Aug. 3, 2019, 2:15 a.m. UTC | #6
Hi Emil:

Thank you for your advice ,
After careful thinking, I decided to modify the code.

Tanks

Emil Velikov <emil.l.velikov@gmail.com> 于2019年7月31日周三 上午12:26写道:
>
> Hi Jerry,
>
> Can you please disable HTML emails for the Gmail web client and reply
> inline. There are multiple articles how to do that.
>
> On 2019/07/26, Jerry Han wrote:
> > Hi Emil Velikov:
> >
> > First of all, thank you for your comments.
> >
> > > Hi Jerry,
> > >
> > > On Thu, 25 Apr 2019 at 08:40, Jerry Han <jerry.han.hq@gmail.com> wrote:
> > > >
> > > > Support Boe Himax8279d 8.0" 1200x1920 TFT LCD panel, it is a MIPI DSI
> > > > panel.
> > > >
> > > > V8:
> > > > - Modify communication address
> > > >
> > > > V7:
> > > > - Add the information of the reviewer
> > > > - Remove unnecessary delays, The udelay_range code gracefully returns
> > > >     without hitting the scheduler on a delay of 0. (Derek)
> > > > - Merge the same data structures, like display_mode and off_cmds (Derek)
> > > > - Optimize the processing of results returned by
> > > >     devm_gpiod_get_optional (Derek)
> > > >
> > > > V6:
> > > > - Add the information of the reviewer (Sam)
> > > > - Delete unnecessary header files #include <linux/fb.h> (Sam)
> > > > - The config DRM_PANEL_BOE_HIMAX8279D appears twice. Drop one of them
> > > (Sam)
> > > > - ADD static, set_gpios function is not used outside this module (Sam)
> > > >
> > > > V5:
> > > > - Added changelog
> > > >
> > > > V4:
> > > > - Frefix all function maes with boe_ (Sam)
> > > > - Fsed "enable_gpio" replace "reset_gpio", Make it look clearer (Sam)
> > > > - Sort include lines alphabetically (Sam)
> > > > - Fixed entries in the makefile must be sorted alphabetically (Sam)
> > > > - Add send_mipi_cmds function to avoid duplicating the code (Sam)
> > > > - Add the necessary delay(reset_delay_t5) between reset and sending
> > > >     the initialization command (Rock wang)
> > > >
> > > > V3:
> > > > - Remove unnecessary delays in sending initialization commands (Jitao
> > > Shi)
> > > >
> > > > V2:
> > > > - Use SPDX identifier (Sam)
> > > > - Use necessary header files replace drmP.h (Sam)
> > > > - Delete unnecessary header files #include <linux/err.h> (Sam)
> > > > - Specifies a GPIOs array to control the reset timing,
> > > >     instead of reading "dsi-reset-sequence" data from DTS (Sam)
> > > > - Delete backlight_disable() function when already disabled (Sam)
> > > > - Use devm_of_find_backlight() replace of_find_backlight_by_node() (Sam)
> > > > - Move the necessary data in the DTS to the current file,
> > > >     like porch, display_mode and Init code etc. (Sam)
> > > > - Add compatible device "boe,himax8279d10p" (Sam)
> > > >
> > > > Signed-off-by: Jerry Han <jerry.han.hq@gmail.com>
> > > > Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
> > > > Reviewed-by: Derek Basehore <dbasehore@chromium.org>
> > > > Cc: Jitao Shi <jitao.shi@mediatek.com>
> > > > Cc: Rock wang <rock_wang@himax.com.cn>
> > > > ---
> > > While the DT has landed, this patch is not merged it seems.
> > > I think that Sam is waiting for a version which does not trigger so
> > > many check-patch warnings.
> > >
> > > That said, a couple of comments if I may.
> > >
> > > > +       struct gpio_desc *enable_gpio;
> > > > +       struct gpio_desc *pp33_gpio;
> > > > +       struct gpio_desc *pp18_gpio;
> > > DT claims that these gpios are required, yet one is using the optional
> > > gpio API.
> > > Is the code off, or does the DT need fixing?
> > >
> > >
> > Thank you for your advice , I will  fix code.
> >
> > > > +static int send_mipi_cmds(struct drm_panel *panel, const struct
> > > panel_cmd *cmds)
> > > > +{
> > > > +       struct panel_info *pinfo = to_panel_info(panel);
> > > > +       unsigned int i = 0;
> > > > +       int err;
> > > > +
> > > > +       if (!cmds)
> > > > +               return -EFAULT;
> > > > +
> > > > +       for (i = 0; cmds[i].len != 0; i++) {
> > > > +               const struct panel_cmd *cmd = &cmds[i];
> > > > +
> > > > +               if (cmd->len == 2)
> > > > +                       err = mipi_dsi_dcs_write(pinfo->link,
> > > > +                                                   cmd->data[1], NULL,
> > > 0);
> > > > +               else
> > > > +                       err = mipi_dsi_dcs_write(pinfo->link,
> > > > +                                                   cmd->data[1],
> > > cmd->data + 2,
> > > > +                                                   cmd->len - 2);
> > > > +
> > > > +               if (err < 0)
> > > > +                       return err;
> > > > +
> > > > +               usleep_range((cmd->data[0]) * 1000,
> > > > +                           (1 + cmd->data[0]) * 1000);
> > > > +       }
> > > > +
> > > This format seems semi-magical. Any particular reason why you're not
> > > using the helpers?
> > > In particular, enter/exit sleep mode and set display on/off.
> > >
> > > Speaking of which - the 8inch display uses then, yet they are missing
> > > for the 10inch one. Seems like there's a bug in there.
> > >
> > > Plus we have some repeating patterns in the vendor/undocumented
> > > commands - good reason to get those into separate hunks.
> > > With the above in place, you can effectively drop the .off_cmd
> > > callback and sleep field from the INIT_CMD arrays.
> > >
> > > Hence, less code to debug and maintain ;-)
> > >
>
> > Normally, we only need to download 0x28 0x10 commands to power-key down.
> > I noticed that helper func (mipi_dsi_dcs_set_display_off,
> > mipi_dsi_dcs_enter_sleep_mode) help me send this commands(0x28 0x10).
> >
> > But based on previous debugging experience, Some vendors are special and
> > may send other commands after sending cmd 0x28 0x10 or before send cmd 0x28
> > 0x10.
> > this problem may also occur in our vendor,
> > so i think this above approach helps me manage code better.
> >
> Using the helpers helper does _not_ prevent you from issuing other
> commands before or after them.
>
> Looking through the existing codebase you'll see plenty of other panel
> drivers doing so.
>
> If anything you'll spot that nearly every driver calls
> mipi_dsi_dcs_set_display_{on,off} in their enable/disable callbacks.
>
> So what I'm suggesting:
>  - use the helpers in the respective callbacks:
> a) display on/off for enable/disable
> b) exit/enter sleep mode for prepare/unprepare
> If any of these cause issues, omit them and adding an inline comment
> clearly explain why they are missing.
>
>  - add explicit delays around the helpers, if needed
>
>  - kill off default_off_cmds and related infra
>
>  - factor out the command stream differences, how you did in for
> reset_delay*. Quck compare shows 8 differences in the 300 commands.
>
>  - kill off the delay stored in data[0]
>
>  - don't repeat the following sequence _12_ times
> _INIT_CMD(0xB0, 0x08),
> ...
> _INIT_CMD(0xCE, 0xFF),
>
>
> With the above in place, the driver will become a lot smaller and easier
> to understand.
>
> Thanks
> -Emil
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index f8e63bcc4c1c..267468ca72bb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4816,6 +4816,12 @@  T:	git git://anongit.freedesktop.org/drm/drm-misc
 S:	Maintained
 F:	drivers/gpu/drm/bochs/
 
+DRM DRIVER FOR BOE HIMAX8279D PANELS
+M:	Jerry Han <hanxu5@huaqin.corp-partner.google.com>
+S:	Maintained
+F:	drivers/gpu/drm/panel/panel-boe-himax8279d.c
+F:	Documentation/devicetree/bindings/display/panel/boe,himax8279d.txt
+
 DRM DRIVER FOR FARADAY TVE200 TV ENCODER
 M:	Linus Walleij <linus.walleij@linaro.org>
 T:	git git://anongit.freedesktop.org/drm/drm-misc
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index f53f817356db..fe2f87cc6627 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -17,6 +17,17 @@  config DRM_PANEL_ARM_VERSATILE
 	  reference designs. The panel is detected using special registers
 	  in the Versatile family syscon registers.
 
+config DRM_PANEL_BOE_HIMAX8279D
+	tristate "Boe Himax8279d panel"
+	depends on OF
+	depends on DRM_MIPI_DSI
+	depends on BACKLIGHT_CLASS_DEVICE
+	help
+	  Say Y here if you want to enable support for Boe Himax8279d
+	  TFT-LCD modules. The panel has a 1200x1920 resolution and uses
+	  24 bit RGB per pixel. It provides a MIPI DSI interface to
+	  the host and has a built-in LED backlight.
+
 config DRM_PANEL_LVDS
 	tristate "Generic LVDS panel driver"
 	depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 7834947a53b0..c4814b6f069e 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -1,5 +1,6 @@ 
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_DRM_PANEL_ARM_VERSATILE) += panel-arm-versatile.o
+obj-$(CONFIG_DRM_PANEL_BOE_HIMAX8279D) += panel-boe-himax8279d.o
 obj-$(CONFIG_DRM_PANEL_LVDS) += panel-lvds.o
 obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
 obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o
diff --git a/drivers/gpu/drm/panel/panel-boe-himax8279d.c b/drivers/gpu/drm/panel/panel-boe-himax8279d.c
new file mode 100644
index 000000000000..9c8ece4fa30a
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-boe-himax8279d.c
@@ -0,0 +1,1050 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019, Huaqin Telecom Technology Co., Ltd
+ *
+ * Author: Jerry Han <jerry.han.hq@gmail.com>
+ *
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#include <linux/gpio/consumer.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_device.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+
+#include <video/mipi_display.h>
+
+struct panel_cmd {
+	size_t len;
+	const char *data;
+};
+
+#define _INIT_CMD(...) { \
+	.len = sizeof((char[]){__VA_ARGS__}), \
+	.data = (char[]){__VA_ARGS__} }
+
+struct panel_desc {
+	const struct drm_display_mode *display_mode;
+	unsigned int bpc;
+	unsigned int width_mm;
+	unsigned int height_mm;
+
+	unsigned int delay_t1;
+	unsigned int reset_delay_t2;
+	unsigned int reset_delay_t3;
+	unsigned int reset_delay_t4;
+	unsigned int reset_delay_t5;
+
+	unsigned long mode_flags;
+	enum mipi_dsi_pixel_format format;
+	unsigned int lanes;
+	const struct panel_cmd *on_cmds;
+	const struct panel_cmd *off_cmds;
+};
+
+struct panel_info {
+	struct drm_panel base;
+	struct mipi_dsi_device *link;
+	const struct panel_desc *desc;
+
+	struct backlight_device *backlight;
+	struct gpio_desc *enable_gpio;
+	struct gpio_desc *pp33_gpio;
+	struct gpio_desc *pp18_gpio;
+
+	bool prepared;
+	bool enabled;
+};
+
+static inline struct panel_info *to_panel_info(struct drm_panel *panel)
+{
+	return container_of(panel, struct panel_info, base);
+}
+
+static void set_gpios(struct panel_info *pinfo, int enable)
+{
+	gpiod_set_value(pinfo->enable_gpio, enable);
+	gpiod_set_value(pinfo->pp33_gpio, enable);
+	gpiod_set_value(pinfo->pp18_gpio, enable);
+}
+
+static int send_mipi_cmds(struct drm_panel *panel, const struct panel_cmd *cmds)
+{
+	struct panel_info *pinfo = to_panel_info(panel);
+	unsigned int i = 0;
+	int err;
+
+	if (!cmds)
+		return -EFAULT;
+
+	for (i = 0; cmds[i].len != 0; i++) {
+		const struct panel_cmd *cmd = &cmds[i];
+
+		if (cmd->len == 2)
+			err = mipi_dsi_dcs_write(pinfo->link,
+						    cmd->data[1], NULL, 0);
+		else
+			err = mipi_dsi_dcs_write(pinfo->link,
+						    cmd->data[1], cmd->data + 2,
+						    cmd->len - 2);
+
+		if (err < 0)
+			return err;
+
+		usleep_range((cmd->data[0]) * 1000,
+			    (1 + cmd->data[0]) * 1000);
+	}
+
+	return 0;
+}
+
+static int boe_panel_disable(struct drm_panel *panel)
+{
+	struct panel_info *pinfo = to_panel_info(panel);
+
+	backlight_disable(pinfo->backlight);
+
+	pinfo->enabled = false;
+
+	return 0;
+}
+
+static int boe_panel_unprepare(struct drm_panel *panel)
+{
+	struct panel_info *pinfo = to_panel_info(panel);
+	int err;
+
+	if (!pinfo->prepared)
+		return 0;
+
+	/* send off code */
+	err = send_mipi_cmds(panel, pinfo->desc->off_cmds);
+	if (err < 0) {
+		DRM_DEV_ERROR(panel->dev,
+				"failed to send DCS Off Code: %d\n", err);
+		goto poweroff;
+	}
+
+	set_gpios(pinfo, 0);
+
+	pinfo->prepared = false;
+
+	return 0;
+
+poweroff:
+	set_gpios(pinfo, 0);
+	return err;
+}
+
+static int boe_panel_prepare(struct drm_panel *panel)
+{
+	struct panel_info *pinfo = to_panel_info(panel);
+	const struct panel_desc *desc = pinfo->desc;
+	int err;
+
+	if (pinfo->prepared)
+		return 0;
+
+	gpiod_set_value(pinfo->pp18_gpio, 1);
+	/* T1 (> 5ms) */
+	usleep_range(desc->delay_t1, 1000 + desc->delay_t1);
+	gpiod_set_value(pinfo->pp33_gpio, 1);
+
+	/* reset sequence */
+	usleep_range(desc->reset_delay_t2, 1000 + desc->reset_delay_t2);
+
+	gpiod_set_value(pinfo->enable_gpio, 1);
+	usleep_range(desc->reset_delay_t3, 1000 + desc->reset_delay_t3);
+	gpiod_set_value(pinfo->enable_gpio, 0);
+
+	usleep_range(desc->reset_delay_t4, 1000 + desc->reset_delay_t4);
+	gpiod_set_value(pinfo->enable_gpio, 1);
+
+	usleep_range(desc->reset_delay_t5, 1000 + desc->reset_delay_t5);
+
+	/* send init code */
+	err = send_mipi_cmds(panel, pinfo->desc->on_cmds);
+	if (err < 0) {
+		DRM_DEV_ERROR(panel->dev,
+				"failed to send DCS Init Code: %d\n", err);
+		goto poweroff;
+	}
+
+	pinfo->prepared = true;
+
+	return 0;
+
+poweroff:
+	set_gpios(pinfo, 0);
+	return err;
+}
+
+static int boe_panel_enable(struct drm_panel *panel)
+{
+	struct panel_info *pinfo = to_panel_info(panel);
+	int ret;
+
+	if (pinfo->enabled)
+		return 0;
+
+	ret = backlight_enable(pinfo->backlight);
+	if (ret) {
+		DRM_DEV_ERROR(panel->drm->dev,
+				"Failed to enable backlight %d\n", ret);
+		return ret;
+	}
+
+	pinfo->enabled = true;
+
+	return 0;
+}
+
+static int boe_panel_get_modes(struct drm_panel *panel)
+{
+	struct panel_info *pinfo = to_panel_info(panel);
+	const struct drm_display_mode *m = pinfo->desc->display_mode;
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(panel->drm, m);
+	if (!mode) {
+		DRM_DEV_ERROR(panel->drm->dev, "failed to add mode %ux%u@%u\n",
+				m->hdisplay, m->vdisplay, m->vrefresh);
+		return -ENOMEM;
+	}
+
+	drm_mode_set_name(mode);
+
+	drm_mode_probed_add(panel->connector, mode);
+
+	panel->connector->display_info.width_mm = pinfo->desc->width_mm;
+	panel->connector->display_info.height_mm = pinfo->desc->height_mm;
+	panel->connector->display_info.bpc = pinfo->desc->bpc;
+
+	return 1;
+}
+
+static const struct drm_panel_funcs panel_funcs = {
+	.disable = boe_panel_disable,
+	.unprepare = boe_panel_unprepare,
+	.prepare = boe_panel_prepare,
+	.enable = boe_panel_enable,
+	.get_modes = boe_panel_get_modes,
+};
+
+static const struct drm_display_mode default_display_mode = {
+	.clock = 159420,
+	.hdisplay = 1200,
+	.hsync_start = 1200 + 80,
+	.hsync_end = 1200 + 80 + 60,
+	.htotal = 1200 + 80 + 60 + 24,
+	.vdisplay = 1920,
+	.vsync_start = 1920 + 10,
+	.vsync_end = 1920 + 10 + 14,
+	.vtotal = 1920 + 10 + 14 + 4,
+	.vrefresh = 60,
+};
+
+static const struct panel_cmd default_off_cmds[] = {
+	_INIT_CMD(0x00, 0x28),
+	_INIT_CMD(0x01, 0x10),
+
+	{},
+};
+
+/* 8 inch */
+static const struct panel_cmd boe_himax8279d8p_on_cmds[] = {
+	_INIT_CMD(0x22, 0x10),
+	_INIT_CMD(0x00, 0xB0, 0x05),
+	_INIT_CMD(0x00, 0xB1, 0xE5),
+	_INIT_CMD(0x00, 0xB3, 0x52),
+	_INIT_CMD(0x00, 0xB0, 0x00),
+	_INIT_CMD(0x00, 0xB3, 0x88),
+	_INIT_CMD(0x00, 0xB0, 0x04),
+	_INIT_CMD(0x00, 0xB8, 0x00),
+	_INIT_CMD(0x00, 0xB0, 0x00),
+	_INIT_CMD(0x00, 0xB2, 0x50),
+	_INIT_CMD(0x00, 0xB6, 0x03),
+	_INIT_CMD(0x00, 0xBA, 0x8B),
+	_INIT_CMD(0x00, 0xBF, 0x15),
+	_INIT_CMD(0x00, 0xC0, 0x0F),
+	_INIT_CMD(0x00, 0xC2, 0x0C),
+	_INIT_CMD(0x00, 0xC3, 0x02),
+	_INIT_CMD(0x00, 0xC4, 0x0C),
+	_INIT_CMD(0x00, 0xC5, 0x02),
+	_INIT_CMD(0x00, 0xB0, 0x01),
+	_INIT_CMD(0x00, 0xE0, 0x26),
+	_INIT_CMD(0x00, 0xE1, 0x26),
+	_INIT_CMD(0x00, 0xDC, 0x00),
+	_INIT_CMD(0x00, 0xDD, 0x00),
+	_INIT_CMD(0x00, 0xCC, 0x26),
+	_INIT_CMD(0x00, 0xCD, 0x26),
+	_INIT_CMD(0x00, 0xC8, 0x00),
+	_INIT_CMD(0x00, 0xC9, 0x00),
+	_INIT_CMD(0x00, 0xD2, 0x04),
+	_INIT_CMD(0x00, 0xD3, 0x04),
+	_INIT_CMD(0x00, 0xE6, 0x03),
+	_INIT_CMD(0x00, 0xE7, 0x03),
+	_INIT_CMD(0x00, 0xC4, 0x08),
+	_INIT_CMD(0x00, 0xC5, 0x08),
+	_INIT_CMD(0x00, 0xD8, 0x07),
+	_INIT_CMD(0x00, 0xD9, 0x07),
+	_INIT_CMD(0x00, 0xC2, 0x06),
+	_INIT_CMD(0x00, 0xC3, 0x06),
+	_INIT_CMD(0x00, 0xD6, 0x05),
+	_INIT_CMD(0x00, 0xD7, 0x05),
+	_INIT_CMD(0x00, 0xC0, 0x0C),
+	_INIT_CMD(0x00, 0xC1, 0x0C),
+	_INIT_CMD(0x00, 0xD4, 0x0B),
+	_INIT_CMD(0x00, 0xD5, 0x0B),
+	_INIT_CMD(0x00, 0xCA, 0x0A),
+	_INIT_CMD(0x00, 0xCB, 0x0A),
+	_INIT_CMD(0x00, 0xDE, 0x09),
+	_INIT_CMD(0x00, 0xDF, 0x09),
+	_INIT_CMD(0x00, 0xC6, 0x26),
+	_INIT_CMD(0x00, 0xC7, 0x26),
+	_INIT_CMD(0x00, 0xCE, 0x00),
+	_INIT_CMD(0x00, 0xCF, 0x00),
+	_INIT_CMD(0x00, 0xDA, 0x26),
+	_INIT_CMD(0x00, 0xDB, 0x26),
+	_INIT_CMD(0x00, 0xE2, 0x00),
+	_INIT_CMD(0x00, 0xE3, 0x00),
+	_INIT_CMD(0x00, 0xB0, 0x02),
+	_INIT_CMD(0x00, 0xC0, 0x00),
+	_INIT_CMD(0x00, 0xC1, 0x07),
+	_INIT_CMD(0x00, 0xC2, 0x0D),
+	_INIT_CMD(0x00, 0xC3, 0x18),
+	_INIT_CMD(0x00, 0xC4, 0x27),
+	_INIT_CMD(0x00, 0xC5, 0x28),
+	_INIT_CMD(0x00, 0xC6, 0x30),
+	_INIT_CMD(0x00, 0xC7, 0x2E),
+	_INIT_CMD(0x00, 0xC8, 0x2F),
+	_INIT_CMD(0x00, 0xC9, 0x1A),
+	_INIT_CMD(0x00, 0xCA, 0x20),
+	_INIT_CMD(0x00, 0xCB, 0x29),
+	_INIT_CMD(0x00, 0xCC, 0x26),
+	_INIT_CMD(0x00, 0xCD, 0x32),
+	_INIT_CMD(0x00, 0xCE, 0x33),
+	_INIT_CMD(0x00, 0xCF, 0x31),
+	_INIT_CMD(0x00, 0xD0, 0x06),
+	_INIT_CMD(0x00, 0xD2, 0x00),
+	_INIT_CMD(0x00, 0xD3, 0x07),
+	_INIT_CMD(0x00, 0xD4, 0x12),
+	_INIT_CMD(0x00, 0xD5, 0x26),
+	_INIT_CMD(0x00, 0xD6, 0x3D),
+	_INIT_CMD(0x00, 0xD7, 0x3F),
+	_INIT_CMD(0x00, 0xD8, 0x3F),
+	_INIT_CMD(0x00, 0xD9, 0x3F),
+	_INIT_CMD(0x00, 0xDA, 0x3F),
+	_INIT_CMD(0x00, 0xDB, 0x3F),
+	_INIT_CMD(0x00, 0xDC, 0x3F),
+	_INIT_CMD(0x00, 0xDD, 0x3F),
+	_INIT_CMD(0x00, 0xDE, 0x3F),
+	_INIT_CMD(0x00, 0xDF, 0x3A),
+	_INIT_CMD(0x00, 0xE0, 0x37),
+	_INIT_CMD(0x00, 0xE1, 0x35),
+	_INIT_CMD(0x00, 0xE2, 0x07),
+	_INIT_CMD(0x00, 0xB0, 0x03),
+	_INIT_CMD(0x00, 0xC8, 0x0B),
+	_INIT_CMD(0x00, 0xC9, 0x07),
+	_INIT_CMD(0x00, 0xC3, 0x00),
+	_INIT_CMD(0x00, 0xE7, 0x00),
+	_INIT_CMD(0x00, 0xC5, 0x2A),
+	_INIT_CMD(0x00, 0xDE, 0x2A),
+	_INIT_CMD(0x00, 0xCA, 0x43),
+	_INIT_CMD(0x00, 0xC9, 0x07),
+	_INIT_CMD(0x00, 0xE4, 0xC0),
+	_INIT_CMD(0x00, 0xE5, 0x0D),
+	_INIT_CMD(0x00, 0xCB, 0x00),
+	_INIT_CMD(0x00, 0xB0, 0x06),
+	_INIT_CMD(0x00, 0xB8, 0xA5),
+	_INIT_CMD(0x00, 0xC0, 0xA5),
+	_INIT_CMD(0x00, 0xC7, 0x0F),
+	_INIT_CMD(0x00, 0xD5, 0x32),
+	_INIT_CMD(0x00, 0xB8, 0x00),
+	_INIT_CMD(0x00, 0xC0, 0x00),
+	_INIT_CMD(0x00, 0xBC, 0x00),
+	_INIT_CMD(0x00, 0xB0, 0x07),
+	_INIT_CMD(0x00, 0xB1, 0x00),
+	_INIT_CMD(0x00, 0xB2, 0x09),
+	_INIT_CMD(0x00, 0xB3, 0x19),
+	_INIT_CMD(0x00, 0xB4, 0x2F),
+	_INIT_CMD(0x00, 0xB5, 0x44),
+	_INIT_CMD(0x00, 0xB6, 0x52),
+	_INIT_CMD(0x00, 0xB7, 0x6A),
+	_INIT_CMD(0x00, 0xB8, 0x8A),
+	_INIT_CMD(0x00, 0xB9, 0xCA),
+	_INIT_CMD(0x00, 0xBA, 0x0C),
+	_INIT_CMD(0x05, 0xBB, 0x87),
+	_INIT_CMD(0x00, 0xBC, 0x06),
+	_INIT_CMD(0x00, 0xBD, 0x0A),
+	_INIT_CMD(0x00, 0xBE, 0x9B),
+	_INIT_CMD(0x00, 0xBF, 0x0C),
+	_INIT_CMD(0x00, 0xC0, 0x3D),
+	_INIT_CMD(0x00, 0xC1, 0x71),
+	_INIT_CMD(0x00, 0xC2, 0x90),
+	_INIT_CMD(0x00, 0xC3, 0xA0),
+	_INIT_CMD(0x00, 0xC4, 0xA8),
+	_INIT_CMD(0x00, 0xC5, 0xB1),
+	_INIT_CMD(0x00, 0xC6, 0xBB),
+	_INIT_CMD(0x00, 0xC7, 0xC0),
+	_INIT_CMD(0x00, 0xC8, 0xC4),
+	_INIT_CMD(0x00, 0xC9, 0x00),
+	_INIT_CMD(0x00, 0xCA, 0x00),
+	_INIT_CMD(0x00, 0xCB, 0x16),
+	_INIT_CMD(0x00, 0xCC, 0xAF),
+	_INIT_CMD(0x00, 0xCD, 0xFF),
+	_INIT_CMD(0x00, 0xCE, 0xFF),
+	_INIT_CMD(0x00, 0xB0, 0x08),
+	_INIT_CMD(0x00, 0xB1, 0x04),
+	_INIT_CMD(0x00, 0xB2, 0x08),
+	_INIT_CMD(0x00, 0xB3, 0x19),
+	_INIT_CMD(0x00, 0xB4, 0x31),
+	_INIT_CMD(0x00, 0xB5, 0x46),
+	_INIT_CMD(0x00, 0xB6, 0x55),
+	_INIT_CMD(0x00, 0xB7, 0x6E),
+	_INIT_CMD(0x00, 0xB8, 0x92),
+	_INIT_CMD(0x00, 0xB9, 0xD4),
+	_INIT_CMD(0x00, 0xBA, 0x1B),
+	_INIT_CMD(0x05, 0xBB, 0x9B),
+	_INIT_CMD(0x00, 0xBC, 0x28),
+	_INIT_CMD(0x00, 0xBD, 0x2D),
+	_INIT_CMD(0x00, 0xBE, 0xC3),
+	_INIT_CMD(0x00, 0xBF, 0x2F),
+	_INIT_CMD(0x00, 0xC0, 0x62),
+	_INIT_CMD(0x00, 0xC1, 0x99),
+	_INIT_CMD(0x00, 0xC2, 0xAB),
+	_INIT_CMD(0x00, 0xC3, 0xBF),
+	_INIT_CMD(0x00, 0xC4, 0xCF),
+	_INIT_CMD(0x00, 0xC5, 0xDF),
+	_INIT_CMD(0x00, 0xC6, 0xF0),
+	_INIT_CMD(0x00, 0xC7, 0xF9),
+	_INIT_CMD(0x00, 0xC8, 0xFC),
+	_INIT_CMD(0x00, 0xC9, 0x00),
+	_INIT_CMD(0x00, 0xCA, 0x00),
+	_INIT_CMD(0x00, 0xCB, 0x16),
+	_INIT_CMD(0x00, 0xCC, 0xAF),
+	_INIT_CMD(0x00, 0xCD, 0xFF),
+	_INIT_CMD(0x00, 0xCE, 0xFF),
+	_INIT_CMD(0x00, 0xB0, 0x09),
+	_INIT_CMD(0x00, 0xB1, 0x04),
+	_INIT_CMD(0x00, 0xB2, 0x05),
+	_INIT_CMD(0x00, 0xB3, 0x17),
+	_INIT_CMD(0x00, 0xB4, 0x2E),
+	_INIT_CMD(0x00, 0xB5, 0x42),
+	_INIT_CMD(0x00, 0xB6, 0x51),
+	_INIT_CMD(0x00, 0xB7, 0x69),
+	_INIT_CMD(0x00, 0xB8, 0x88),
+	_INIT_CMD(0x00, 0xB9, 0xC9),
+	_INIT_CMD(0x00, 0xBA, 0x0C),
+	_INIT_CMD(0x05, 0xBB, 0x86),
+	_INIT_CMD(0x00, 0xBC, 0x03),
+	_INIT_CMD(0x00, 0xBD, 0x08),
+	_INIT_CMD(0x00, 0xBE, 0x95),
+	_INIT_CMD(0x00, 0xBF, 0x05),
+	_INIT_CMD(0x00, 0xC0, 0x35),
+	_INIT_CMD(0x00, 0xC1, 0x62),
+	_INIT_CMD(0x00, 0xC2, 0x81),
+	_INIT_CMD(0x00, 0xC3, 0x96),
+	_INIT_CMD(0x00, 0xC4, 0x9E),
+	_INIT_CMD(0x00, 0xC5, 0xA5),
+	_INIT_CMD(0x00, 0xC6, 0xAD),
+	_INIT_CMD(0x00, 0xC7, 0xB1),
+	_INIT_CMD(0x00, 0xC8, 0xB4),
+	_INIT_CMD(0x00, 0xC9, 0x00),
+	_INIT_CMD(0x00, 0xCA, 0x00),
+	_INIT_CMD(0x00, 0xCB, 0x16),
+	_INIT_CMD(0x00, 0xCC, 0xAF),
+	_INIT_CMD(0x00, 0xCD, 0xFF),
+	_INIT_CMD(0x00, 0xCE, 0xFF),
+	_INIT_CMD(0x00, 0xB0, 0x0A),
+	_INIT_CMD(0x00, 0xB1, 0x00),
+	_INIT_CMD(0x00, 0xB2, 0x09),
+	_INIT_CMD(0x00, 0xB3, 0x19),
+	_INIT_CMD(0x00, 0xB4, 0x2F),
+	_INIT_CMD(0x00, 0xB5, 0x44),
+	_INIT_CMD(0x00, 0xB6, 0x52),
+	_INIT_CMD(0x00, 0xB7, 0x6A),
+	_INIT_CMD(0x00, 0xB8, 0x8A),
+	_INIT_CMD(0x00, 0xB9, 0xCA),
+	_INIT_CMD(0x00, 0xBA, 0x0C),
+	_INIT_CMD(0x05, 0xBB, 0x87),
+	_INIT_CMD(0x00, 0xBC, 0x06),
+	_INIT_CMD(0x00, 0xBD, 0x0A),
+	_INIT_CMD(0x00, 0xBE, 0x9B),
+	_INIT_CMD(0x00, 0xBF, 0x0C),
+	_INIT_CMD(0x00, 0xC0, 0x3D),
+	_INIT_CMD(0x00, 0xC1, 0x71),
+	_INIT_CMD(0x00, 0xC2, 0x90),
+	_INIT_CMD(0x00, 0xC3, 0xA0),
+	_INIT_CMD(0x00, 0xC4, 0xA8),
+	_INIT_CMD(0x00, 0xC5, 0xB1),
+	_INIT_CMD(0x00, 0xC6, 0xBB),
+	_INIT_CMD(0x00, 0xC7, 0xC0),
+	_INIT_CMD(0x00, 0xC8, 0xC4),
+	_INIT_CMD(0x00, 0xC9, 0x00),
+	_INIT_CMD(0x00, 0xCA, 0x00),
+	_INIT_CMD(0x00, 0xCB, 0x16),
+	_INIT_CMD(0x00, 0xCC, 0xAF),
+	_INIT_CMD(0x00, 0xCD, 0xFF),
+	_INIT_CMD(0x00, 0xCE, 0xFF),
+	_INIT_CMD(0x00, 0xB0, 0x0B),
+	_INIT_CMD(0x00, 0xB1, 0x04),
+	_INIT_CMD(0x00, 0xB2, 0x08),
+	_INIT_CMD(0x00, 0xB3, 0x19),
+	_INIT_CMD(0x00, 0xB4, 0x31),
+	_INIT_CMD(0x00, 0xB5, 0x46),
+	_INIT_CMD(0x00, 0xB6, 0x55),
+	_INIT_CMD(0x00, 0xB7, 0x6E),
+	_INIT_CMD(0x00, 0xB8, 0x92),
+	_INIT_CMD(0x00, 0xB9, 0xD4),
+	_INIT_CMD(0x00, 0xBA, 0x1B),
+	_INIT_CMD(0x05, 0xBB, 0x9B),
+	_INIT_CMD(0x00, 0xBC, 0x28),
+	_INIT_CMD(0x00, 0xBD, 0x2D),
+	_INIT_CMD(0x00, 0xBE, 0xC3),
+	_INIT_CMD(0x00, 0xBF, 0x2F),
+	_INIT_CMD(0x00, 0xC0, 0x62),
+	_INIT_CMD(0x00, 0xC1, 0x99),
+	_INIT_CMD(0x00, 0xC2, 0xAB),
+	_INIT_CMD(0x00, 0xC3, 0xBF),
+	_INIT_CMD(0x00, 0xC4, 0xCF),
+	_INIT_CMD(0x00, 0xC5, 0xDF),
+	_INIT_CMD(0x00, 0xC6, 0xF0),
+	_INIT_CMD(0x00, 0xC7, 0xF9),
+	_INIT_CMD(0x00, 0xC8, 0xFC),
+	_INIT_CMD(0x00, 0xC9, 0x00),
+	_INIT_CMD(0x00, 0xCA, 0x00),
+	_INIT_CMD(0x00, 0xCB, 0x16),
+	_INIT_CMD(0x00, 0xCC, 0xAF),
+	_INIT_CMD(0x00, 0xCD, 0xFF),
+	_INIT_CMD(0x00, 0xCE, 0xFF),
+	_INIT_CMD(0x00, 0xB0, 0x0C),
+	_INIT_CMD(0x00, 0xB1, 0x04),
+	_INIT_CMD(0x00, 0xB2, 0x05),
+	_INIT_CMD(0x00, 0xB3, 0x17),
+	_INIT_CMD(0x00, 0xB4, 0x2E),
+	_INIT_CMD(0x00, 0xB5, 0x42),
+	_INIT_CMD(0x00, 0xB6, 0x51),
+	_INIT_CMD(0x00, 0xB7, 0x69),
+	_INIT_CMD(0x00, 0xB8, 0x88),
+	_INIT_CMD(0x00, 0xB9, 0xC9),
+	_INIT_CMD(0x00, 0xBA, 0x0C),
+	_INIT_CMD(0x05, 0xBB, 0x86),
+	_INIT_CMD(0x00, 0xBC, 0x03),
+	_INIT_CMD(0x00, 0xBD, 0x08),
+	_INIT_CMD(0x00, 0xBE, 0x95),
+	_INIT_CMD(0x00, 0xBF, 0x05),
+	_INIT_CMD(0x00, 0xC0, 0x35),
+	_INIT_CMD(0x00, 0xC1, 0x62),
+	_INIT_CMD(0x00, 0xC2, 0x81),
+	_INIT_CMD(0x00, 0xC3, 0x96),
+	_INIT_CMD(0x00, 0xC4, 0x9E),
+	_INIT_CMD(0x00, 0xC5, 0xA5),
+	_INIT_CMD(0x00, 0xC6, 0xAD),
+	_INIT_CMD(0x00, 0xC7, 0xB1),
+	_INIT_CMD(0x00, 0xC8, 0xB4),
+	_INIT_CMD(0x00, 0xC9, 0x00),
+	_INIT_CMD(0x00, 0xCA, 0x00),
+	_INIT_CMD(0x00, 0xCB, 0x16),
+	_INIT_CMD(0x00, 0xCC, 0xAF),
+	_INIT_CMD(0x00, 0xCD, 0xFF),
+	_INIT_CMD(0x64, 0xCE, 0xFF),
+	_INIT_CMD(0x00, 0xB0, 0x00),
+	_INIT_CMD(0x00, 0xB3, 0x08),
+	_INIT_CMD(0x00, 0xB0, 0x04),
+	_INIT_CMD(0x0A, 0xB8, 0x68),
+	_INIT_CMD(0x78, 0x11),
+	_INIT_CMD(0x14, 0x29),
+
+	{},
+};
+
+static const struct panel_desc boe_himax8279d8p_panel_desc = {
+	.display_mode = &default_display_mode,
+	.bpc = 8,
+	.width_mm = 107,
+	.height_mm = 172,
+	.delay_t1 = 5000,
+	.reset_delay_t2 = 14000,
+	.reset_delay_t3 = 1000,
+	.reset_delay_t4 = 1000,
+	.reset_delay_t5 = 5000,
+	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+			MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,
+	.format = MIPI_DSI_FMT_RGB888,
+	.lanes = 4,
+	.on_cmds = boe_himax8279d8p_on_cmds,
+	.off_cmds = default_off_cmds,
+};
+
+/* 10 inch */
+static const struct panel_cmd boe_himax8279d10p_on_cmds[] = {
+	_INIT_CMD(0x00, 0xB0, 0x05),
+	_INIT_CMD(0x00, 0xB1, 0xE5),
+	_INIT_CMD(0x00, 0xB3, 0x52),
+	_INIT_CMD(0x00, 0xB0, 0x00),
+	_INIT_CMD(0x00, 0xB3, 0x88),
+	_INIT_CMD(0x00, 0xB0, 0x04),
+	_INIT_CMD(0x00, 0xB8, 0x00),
+	_INIT_CMD(0x00, 0xB0, 0x00),
+	_INIT_CMD(0x00, 0xB2, 0x50),
+	_INIT_CMD(0x00, 0xB6, 0x03),
+	_INIT_CMD(0x00, 0xBA, 0x8B),
+	_INIT_CMD(0x00, 0xBF, 0x1A),
+	_INIT_CMD(0x00, 0xC0, 0x0F),
+	_INIT_CMD(0x00, 0xC2, 0x0C),
+	_INIT_CMD(0x00, 0xC3, 0x02),
+	_INIT_CMD(0x00, 0xC4, 0x0C),
+	_INIT_CMD(0x00, 0xC5, 0x02),
+	_INIT_CMD(0x00, 0xB0, 0x01),
+	_INIT_CMD(0x00, 0xE0, 0x26),
+	_INIT_CMD(0x00, 0xE1, 0x26),
+	_INIT_CMD(0x00, 0xDC, 0x00),
+	_INIT_CMD(0x00, 0xDD, 0x00),
+	_INIT_CMD(0x00, 0xCC, 0x26),
+	_INIT_CMD(0x00, 0xCD, 0x26),
+	_INIT_CMD(0x00, 0xC8, 0x00),
+	_INIT_CMD(0x00, 0xC9, 0x00),
+	_INIT_CMD(0x00, 0xD2, 0x04),
+	_INIT_CMD(0x00, 0xD3, 0x04),
+	_INIT_CMD(0x00, 0xE6, 0x03),
+	_INIT_CMD(0x00, 0xE7, 0x03),
+	_INIT_CMD(0x00, 0xC4, 0x08),
+	_INIT_CMD(0x00, 0xC5, 0x08),
+	_INIT_CMD(0x00, 0xD8, 0x07),
+	_INIT_CMD(0x00, 0xD9, 0x07),
+	_INIT_CMD(0x00, 0xC2, 0x06),
+	_INIT_CMD(0x00, 0xC3, 0x06),
+	_INIT_CMD(0x00, 0xD6, 0x05),
+	_INIT_CMD(0x00, 0xD7, 0x05),
+	_INIT_CMD(0x00, 0xC0, 0x0C),
+	_INIT_CMD(0x00, 0xC1, 0x0C),
+	_INIT_CMD(0x00, 0xD4, 0x0B),
+	_INIT_CMD(0x00, 0xD5, 0x0B),
+	_INIT_CMD(0x00, 0xCA, 0x0A),
+	_INIT_CMD(0x00, 0xCB, 0x0A),
+	_INIT_CMD(0x00, 0xDE, 0x09),
+	_INIT_CMD(0x00, 0xDF, 0x09),
+	_INIT_CMD(0x00, 0xC6, 0x26),
+	_INIT_CMD(0x00, 0xC7, 0x26),
+	_INIT_CMD(0x00, 0xCE, 0x00),
+	_INIT_CMD(0x00, 0xCF, 0x00),
+	_INIT_CMD(0x00, 0xDA, 0x26),
+	_INIT_CMD(0x00, 0xDB, 0x26),
+	_INIT_CMD(0x00, 0xE2, 0x00),
+	_INIT_CMD(0x00, 0xE3, 0x00),
+	_INIT_CMD(0x00, 0xB0, 0x02),
+	_INIT_CMD(0x00, 0xC0, 0x00),
+	_INIT_CMD(0x00, 0xC1, 0x07),
+	_INIT_CMD(0x00, 0xC2, 0x0D),
+	_INIT_CMD(0x00, 0xC3, 0x18),
+	_INIT_CMD(0x00, 0xC4, 0x27),
+	_INIT_CMD(0x00, 0xC5, 0x28),
+	_INIT_CMD(0x00, 0xC6, 0x30),
+	_INIT_CMD(0x00, 0xC7, 0x2E),
+	_INIT_CMD(0x00, 0xC8, 0x2F),
+	_INIT_CMD(0x00, 0xC9, 0x1A),
+	_INIT_CMD(0x00, 0xCA, 0x20),
+	_INIT_CMD(0x00, 0xCB, 0x29),
+	_INIT_CMD(0x00, 0xCC, 0x26),
+	_INIT_CMD(0x00, 0xCD, 0x32),
+	_INIT_CMD(0x00, 0xCE, 0x33),
+	_INIT_CMD(0x00, 0xCF, 0x31),
+	_INIT_CMD(0x00, 0xD0, 0x06),
+	_INIT_CMD(0x00, 0xD2, 0x00),
+	_INIT_CMD(0x00, 0xD3, 0x07),
+	_INIT_CMD(0x00, 0xD4, 0x12),
+	_INIT_CMD(0x00, 0xD5, 0x26),
+	_INIT_CMD(0x00, 0xD6, 0x3D),
+	_INIT_CMD(0x00, 0xD7, 0x3F),
+	_INIT_CMD(0x00, 0xD8, 0x3F),
+	_INIT_CMD(0x00, 0xD9, 0x3F),
+	_INIT_CMD(0x00, 0xDA, 0x3F),
+	_INIT_CMD(0x00, 0xDB, 0x3F),
+	_INIT_CMD(0x00, 0xDC, 0x3F),
+	_INIT_CMD(0x00, 0xDD, 0x3F),
+	_INIT_CMD(0x00, 0xDE, 0x3F),
+	_INIT_CMD(0x00, 0xDF, 0x3A),
+	_INIT_CMD(0x00, 0xE0, 0x37),
+	_INIT_CMD(0x00, 0xE1, 0x35),
+	_INIT_CMD(0x00, 0xE2, 0x07),
+	_INIT_CMD(0x00, 0xB0, 0x03),
+	_INIT_CMD(0x00, 0xC8, 0x0B),
+	_INIT_CMD(0x00, 0xC9, 0x07),
+	_INIT_CMD(0x00, 0xC3, 0x00),
+	_INIT_CMD(0x00, 0xE7, 0x00),
+	_INIT_CMD(0x00, 0xC5, 0x2A),
+	_INIT_CMD(0x00, 0xDE, 0x2A),
+	_INIT_CMD(0x00, 0xCA, 0x43),
+	_INIT_CMD(0x00, 0xC9, 0x07),
+	_INIT_CMD(0x00, 0xE4, 0xC0),
+	_INIT_CMD(0x00, 0xE5, 0x0D),
+	_INIT_CMD(0x00, 0xCB, 0x00),
+	_INIT_CMD(0x00, 0xB0, 0x06),
+	_INIT_CMD(0x00, 0xB8, 0xA5),
+	_INIT_CMD(0x00, 0xC0, 0xA5),
+	_INIT_CMD(0x00, 0xC7, 0x0F),
+	_INIT_CMD(0x00, 0xD5, 0x32),
+	_INIT_CMD(0x00, 0xB8, 0x00),
+	_INIT_CMD(0x00, 0xC0, 0x00),
+	_INIT_CMD(0x00, 0xBC, 0x00),
+	_INIT_CMD(0x00, 0xB0, 0x07),
+	_INIT_CMD(0x00, 0xB1, 0x00),
+	_INIT_CMD(0x00, 0xB2, 0x09),
+	_INIT_CMD(0x00, 0xB3, 0x19),
+	_INIT_CMD(0x00, 0xB4, 0x2F),
+	_INIT_CMD(0x00, 0xB5, 0x44),
+	_INIT_CMD(0x00, 0xB6, 0x52),
+	_INIT_CMD(0x00, 0xB7, 0x6A),
+	_INIT_CMD(0x00, 0xB8, 0x8A),
+	_INIT_CMD(0x00, 0xB9, 0xCA),
+	_INIT_CMD(0x00, 0xBA, 0x0C),
+	_INIT_CMD(0x00, 0xBB, 0x87),
+	_INIT_CMD(0x00, 0xBC, 0x06),
+	_INIT_CMD(0x00, 0xBD, 0x0A),
+	_INIT_CMD(0x00, 0xBE, 0x9B),
+	_INIT_CMD(0x00, 0xBF, 0x0C),
+	_INIT_CMD(0x00, 0xC0, 0x3D),
+	_INIT_CMD(0x00, 0xC1, 0x71),
+	_INIT_CMD(0x00, 0xC2, 0x90),
+	_INIT_CMD(0x00, 0xC3, 0xA0),
+	_INIT_CMD(0x00, 0xC4, 0xA8),
+	_INIT_CMD(0x00, 0xC5, 0xB1),
+	_INIT_CMD(0x00, 0xC6, 0xBB),
+	_INIT_CMD(0x00, 0xC7, 0xC0),
+	_INIT_CMD(0x00, 0xC8, 0xC4),
+	_INIT_CMD(0x00, 0xC9, 0x00),
+	_INIT_CMD(0x00, 0xCA, 0x00),
+	_INIT_CMD(0x00, 0xCB, 0x16),
+	_INIT_CMD(0x00, 0xCC, 0xAF),
+	_INIT_CMD(0x00, 0xCD, 0xFF),
+	_INIT_CMD(0x00, 0xCE, 0xFF),
+	_INIT_CMD(0x00, 0xB0, 0x08),
+	_INIT_CMD(0x00, 0xB1, 0x04),
+	_INIT_CMD(0x00, 0xB2, 0x08),
+	_INIT_CMD(0x00, 0xB3, 0x19),
+	_INIT_CMD(0x00, 0xB4, 0x31),
+	_INIT_CMD(0x00, 0xB5, 0x46),
+	_INIT_CMD(0x00, 0xB6, 0x55),
+	_INIT_CMD(0x00, 0xB7, 0x6E),
+	_INIT_CMD(0x00, 0xB8, 0x92),
+	_INIT_CMD(0x00, 0xB9, 0xD4),
+	_INIT_CMD(0x00, 0xBA, 0x1B),
+	_INIT_CMD(0x00, 0xBB, 0x9B),
+	_INIT_CMD(0x00, 0xBC, 0x28),
+	_INIT_CMD(0x00, 0xBD, 0x2D),
+	_INIT_CMD(0x00, 0xBE, 0xC3),
+	_INIT_CMD(0x00, 0xBF, 0x2F),
+	_INIT_CMD(0x00, 0xC0, 0x62),
+	_INIT_CMD(0x00, 0xC1, 0x99),
+	_INIT_CMD(0x00, 0xC2, 0xAB),
+	_INIT_CMD(0x00, 0xC3, 0xBF),
+	_INIT_CMD(0x00, 0xC4, 0xCF),
+	_INIT_CMD(0x00, 0xC5, 0xDF),
+	_INIT_CMD(0x00, 0xC6, 0xF0),
+	_INIT_CMD(0x00, 0xC7, 0xF9),
+	_INIT_CMD(0x00, 0xC8, 0xFC),
+	_INIT_CMD(0x00, 0xC9, 0x00),
+	_INIT_CMD(0x00, 0xCA, 0x00),
+	_INIT_CMD(0x00, 0xCB, 0x16),
+	_INIT_CMD(0x00, 0xCC, 0xAF),
+	_INIT_CMD(0x00, 0xCD, 0xFF),
+	_INIT_CMD(0x00, 0xCE, 0xFF),
+	_INIT_CMD(0x00, 0xB0, 0x09),
+	_INIT_CMD(0x00, 0xB1, 0x04),
+	_INIT_CMD(0x00, 0xB2, 0x05),
+	_INIT_CMD(0x00, 0xB3, 0x17),
+	_INIT_CMD(0x00, 0xB4, 0x2E),
+	_INIT_CMD(0x00, 0xB5, 0x42),
+	_INIT_CMD(0x00, 0xB6, 0x51),
+	_INIT_CMD(0x00, 0xB7, 0x69),
+	_INIT_CMD(0x00, 0xB8, 0x88),
+	_INIT_CMD(0x00, 0xB9, 0xC9),
+	_INIT_CMD(0x00, 0xBA, 0x0C),
+	_INIT_CMD(0x00, 0xBB, 0x86),
+	_INIT_CMD(0x00, 0xBC, 0x03),
+	_INIT_CMD(0x00, 0xBD, 0x08),
+	_INIT_CMD(0x00, 0xBE, 0x95),
+	_INIT_CMD(0x00, 0xBF, 0x05),
+	_INIT_CMD(0x00, 0xC0, 0x35),
+	_INIT_CMD(0x00, 0xC1, 0x62),
+	_INIT_CMD(0x00, 0xC2, 0x81),
+	_INIT_CMD(0x00, 0xC3, 0x96),
+	_INIT_CMD(0x00, 0xC4, 0x9E),
+	_INIT_CMD(0x00, 0xC5, 0xA5),
+	_INIT_CMD(0x00, 0xC6, 0xAD),
+	_INIT_CMD(0x00, 0xC7, 0xB1),
+	_INIT_CMD(0x00, 0xC8, 0xB4),
+	_INIT_CMD(0x00, 0xC9, 0x00),
+	_INIT_CMD(0x00, 0xCA, 0x00),
+	_INIT_CMD(0x00, 0xCB, 0x16),
+	_INIT_CMD(0x00, 0xCC, 0xAF),
+	_INIT_CMD(0x00, 0xCD, 0xFF),
+	_INIT_CMD(0x00, 0xCE, 0xFF),
+	_INIT_CMD(0x00, 0xB0, 0x0A),
+	_INIT_CMD(0x00, 0xB1, 0x00),
+	_INIT_CMD(0x00, 0xB2, 0x09),
+	_INIT_CMD(0x00, 0xB3, 0x19),
+	_INIT_CMD(0x00, 0xB4, 0x2F),
+	_INIT_CMD(0x00, 0xB5, 0x44),
+	_INIT_CMD(0x00, 0xB6, 0x52),
+	_INIT_CMD(0x00, 0xB7, 0x6A),
+	_INIT_CMD(0x00, 0xB8, 0x8A),
+	_INIT_CMD(0x00, 0xB9, 0xCA),
+	_INIT_CMD(0x00, 0xBA, 0x0C),
+	_INIT_CMD(0x00, 0xBB, 0x87),
+	_INIT_CMD(0x00, 0xBC, 0x06),
+	_INIT_CMD(0x00, 0xBD, 0x0A),
+	_INIT_CMD(0x00, 0xBE, 0x9B),
+	_INIT_CMD(0x00, 0xBF, 0x0C),
+	_INIT_CMD(0x00, 0xC0, 0x3D),
+	_INIT_CMD(0x00, 0xC1, 0x71),
+	_INIT_CMD(0x00, 0xC2, 0x90),
+	_INIT_CMD(0x00, 0xC3, 0xA0),
+	_INIT_CMD(0x00, 0xC4, 0xA8),
+	_INIT_CMD(0x00, 0xC5, 0xB1),
+	_INIT_CMD(0x00, 0xC6, 0xBB),
+	_INIT_CMD(0x00, 0xC7, 0xC0),
+	_INIT_CMD(0x00, 0xC8, 0xC4),
+	_INIT_CMD(0x00, 0xC9, 0x00),
+	_INIT_CMD(0x00, 0xCA, 0x00),
+	_INIT_CMD(0x00, 0xCB, 0x16),
+	_INIT_CMD(0x00, 0xCC, 0xAF),
+	_INIT_CMD(0x00, 0xCD, 0xFF),
+	_INIT_CMD(0x00, 0xCE, 0xFF),
+	_INIT_CMD(0x00, 0xB0, 0x0B),
+	_INIT_CMD(0x00, 0xB1, 0x04),
+	_INIT_CMD(0x00, 0xB2, 0x08),
+	_INIT_CMD(0x00, 0xB3, 0x19),
+	_INIT_CMD(0x00, 0xB4, 0x31),
+	_INIT_CMD(0x00, 0xB5, 0x46),
+	_INIT_CMD(0x00, 0xB6, 0x55),
+	_INIT_CMD(0x00, 0xB7, 0x6E),
+	_INIT_CMD(0x00, 0xB8, 0x92),
+	_INIT_CMD(0x00, 0xB9, 0xD4),
+	_INIT_CMD(0x00, 0xBA, 0x1B),
+	_INIT_CMD(0x00, 0xBB, 0x9B),
+	_INIT_CMD(0x00, 0xBC, 0x28),
+	_INIT_CMD(0x00, 0xBD, 0x2D),
+	_INIT_CMD(0x00, 0xBE, 0xC3),
+	_INIT_CMD(0x00, 0xBF, 0x2F),
+	_INIT_CMD(0x00, 0xC0, 0x62),
+	_INIT_CMD(0x00, 0xC1, 0x99),
+	_INIT_CMD(0x00, 0xC2, 0xAB),
+	_INIT_CMD(0x00, 0xC3, 0xBF),
+	_INIT_CMD(0x00, 0xC4, 0xCF),
+	_INIT_CMD(0x00, 0xC5, 0xDF),
+	_INIT_CMD(0x00, 0xC6, 0xF0),
+	_INIT_CMD(0x00, 0xC7, 0xF9),
+	_INIT_CMD(0x00, 0xC8, 0xFC),
+	_INIT_CMD(0x00, 0xC9, 0x00),
+	_INIT_CMD(0x00, 0xCA, 0x00),
+	_INIT_CMD(0x00, 0xCB, 0x16),
+	_INIT_CMD(0x00, 0xCC, 0xAF),
+	_INIT_CMD(0x00, 0xCD, 0xFF),
+	_INIT_CMD(0x00, 0xCE, 0xFF),
+	_INIT_CMD(0x00, 0xB0, 0x0C),
+	_INIT_CMD(0x00, 0xB1, 0x04),
+	_INIT_CMD(0x00, 0xB2, 0x05),
+	_INIT_CMD(0x00, 0xB3, 0x17),
+	_INIT_CMD(0x00, 0xB4, 0x2E),
+	_INIT_CMD(0x00, 0xB5, 0x42),
+	_INIT_CMD(0x00, 0xB6, 0x51),
+	_INIT_CMD(0x00, 0xB7, 0x69),
+	_INIT_CMD(0x00, 0xB8, 0x88),
+	_INIT_CMD(0x00, 0xB9, 0xC9),
+	_INIT_CMD(0x00, 0xBA, 0x0C),
+	_INIT_CMD(0x00, 0xBB, 0x86),
+	_INIT_CMD(0x00, 0xBC, 0x03),
+	_INIT_CMD(0x00, 0xBD, 0x08),
+	_INIT_CMD(0x00, 0xBE, 0x95),
+	_INIT_CMD(0x00, 0xBF, 0x05),
+	_INIT_CMD(0x00, 0xC0, 0x35),
+	_INIT_CMD(0x00, 0xC1, 0x62),
+	_INIT_CMD(0x00, 0xC2, 0x81),
+	_INIT_CMD(0x00, 0xC3, 0x96),
+	_INIT_CMD(0x00, 0xC4, 0x9E),
+	_INIT_CMD(0x00, 0xC5, 0xA5),
+	_INIT_CMD(0x00, 0xC6, 0xAD),
+	_INIT_CMD(0x00, 0xC7, 0xB1),
+	_INIT_CMD(0x00, 0xC8, 0xB4),
+	_INIT_CMD(0x00, 0xC9, 0x00),
+	_INIT_CMD(0x00, 0xCA, 0x00),
+	_INIT_CMD(0x00, 0xCB, 0x16),
+	_INIT_CMD(0x00, 0xCC, 0xAF),
+	_INIT_CMD(0x00, 0xCD, 0xFF),
+	_INIT_CMD(0x00, 0xCE, 0xFF),
+	_INIT_CMD(0x00, 0xB0, 0x00),
+	_INIT_CMD(0x00, 0xB3, 0x08),
+	_INIT_CMD(0x00, 0xB0, 0x04),
+	_INIT_CMD(0x64, 0xB8, 0x68),
+
+	{},
+};
+
+static const struct panel_desc boe_himax8279d10p_panel_desc = {
+	.display_mode = &default_display_mode,
+	.bpc = 8,
+	.width_mm = 135,
+	.height_mm = 216,
+	.delay_t1 = 5000,
+	.reset_delay_t2 = 14000,
+	.reset_delay_t3 = 1000,
+	.reset_delay_t4 = 1000,
+	.reset_delay_t5 = 5000,
+	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+			MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM,
+	.format = MIPI_DSI_FMT_RGB888,
+	.lanes = 4,
+	.on_cmds = boe_himax8279d10p_on_cmds,
+	.off_cmds = default_off_cmds,
+};
+
+static const struct of_device_id panel_of_match[] = {
+	{ .compatible = "boe,himax8279d8p",
+	  .data = &boe_himax8279d8p_panel_desc
+	}, { .compatible = "boe,himax8279d10p",
+	  .data = &boe_himax8279d10p_panel_desc
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(of, panel_of_match);
+
+static int panel_add(struct panel_info *pinfo)
+{
+	struct device *dev = &pinfo->link->dev;
+	int ret;
+
+	pinfo->pp18_gpio = devm_gpiod_get_optional(dev, "pp18", GPIOD_OUT_HIGH);
+	if (IS_ERR(pinfo->pp18_gpio)) {
+		ret = PTR_ERR(pinfo->pp18_gpio);
+		if (ret != -EPROBE_DEFER)
+			DRM_DEV_ERROR(dev, "failed to get pp18 gpio: %d\n",
+					ret);
+		return ret;
+	}
+
+	pinfo->pp33_gpio = devm_gpiod_get_optional(dev, "pp33", GPIOD_OUT_HIGH);
+	if (IS_ERR(pinfo->pp33_gpio)) {
+		ret = PTR_ERR(pinfo->pp33_gpio);
+		if (ret != -EPROBE_DEFER)
+			DRM_DEV_ERROR(dev, "failed to get pp33 gpio: %d\n",
+					ret);
+		return ret;
+	}
+
+	pinfo->enable_gpio = devm_gpiod_get_optional(dev, "enable",
+							GPIOD_OUT_HIGH);
+	if (IS_ERR(pinfo->enable_gpio)) {
+		ret = PTR_ERR(pinfo->enable_gpio);
+		if (ret != -EPROBE_DEFER)
+			DRM_DEV_ERROR(dev, "failed to get enable gpio: %d\n",
+					ret);
+		return ret;
+	}
+
+	pinfo->backlight = devm_of_find_backlight(dev);
+	if (IS_ERR(pinfo->backlight))
+		return PTR_ERR(pinfo->backlight);
+
+	drm_panel_init(&pinfo->base);
+	pinfo->base.funcs = &panel_funcs;
+	pinfo->base.dev = &pinfo->link->dev;
+
+	ret = drm_panel_add(&pinfo->base);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static void panel_del(struct panel_info *pinfo)
+{
+	if (pinfo->base.dev)
+		drm_panel_remove(&pinfo->base);
+}
+
+static int panel_probe(struct mipi_dsi_device *dsi)
+{
+	struct panel_info *pinfo;
+	const struct panel_desc *desc;
+	int err;
+
+	pinfo = devm_kzalloc(&dsi->dev, sizeof(*pinfo), GFP_KERNEL);
+	if (!pinfo)
+		return -ENOMEM;
+
+	desc = of_device_get_match_data(&dsi->dev);
+	dsi->mode_flags = desc->mode_flags;
+	dsi->format = desc->format;
+	dsi->lanes = desc->lanes;
+	pinfo->desc = desc;
+
+	pinfo->link = dsi;
+	mipi_dsi_set_drvdata(dsi, pinfo);
+
+	err = panel_add(pinfo);
+	if (err < 0)
+		return err;
+
+	return mipi_dsi_attach(dsi);
+}
+
+static int panel_remove(struct mipi_dsi_device *dsi)
+{
+	struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
+	int err;
+
+	err = boe_panel_unprepare(&pinfo->base);
+	if (err < 0)
+		DRM_DEV_ERROR(&dsi->dev, "failed to unprepare panel: %d\n",
+				err);
+
+	err = boe_panel_disable(&pinfo->base);
+	if (err < 0)
+		DRM_DEV_ERROR(&dsi->dev, "failed to disable panel: %d\n", err);
+
+	err = mipi_dsi_detach(dsi);
+	if (err < 0)
+		DRM_DEV_ERROR(&dsi->dev, "failed to detach from DSI host: %d\n",
+				err);
+
+	drm_panel_detach(&pinfo->base);
+	panel_del(pinfo);
+
+	return 0;
+}
+
+static void panel_shutdown(struct mipi_dsi_device *dsi)
+{
+	struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
+
+	boe_panel_disable(&pinfo->base);
+	boe_panel_unprepare(&pinfo->base);
+}
+
+static struct mipi_dsi_driver panel_driver = {
+	.driver = {
+		.name = "panel-boe-himax8279d",
+		.of_match_table = panel_of_match,
+	},
+	.probe = panel_probe,
+	.remove = panel_remove,
+	.shutdown = panel_shutdown,
+};
+module_mipi_dsi_driver(panel_driver);
+
+MODULE_AUTHOR("Jerry Han <jerry.han.hq@gmail.com>");
+MODULE_DESCRIPTION("Boe Himax8279d driver");
+MODULE_LICENSE("GPL v2");