// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019, Huaqin Telecom Technology Co., Ltd
*
* Author: Jerry Han <jerry.han.hq@gmail.com>
*
*/
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.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 <video/mipi_display.h>
struct panel_cmd {
char cmd;
char data;
};
struct panel_desc {
const struct drm_display_mode *display_mode;
unsigned int bpc;
unsigned int width_mm;
unsigned int height_mm;
unsigned long mode_flags;
enum mipi_dsi_pixel_format format;
unsigned int lanes;
const struct panel_cmd *on_cmds;
unsigned int on_cmds_num;
};
struct panel_info {
struct drm_panel base;
struct mipi_dsi_device *link;
const struct panel_desc *desc;
struct gpio_desc *enable_gpio;
struct gpio_desc *pp33_gpio;
struct gpio_desc *pp18_gpio;
};
static inline struct panel_info *to_panel_info(struct drm_panel *panel)
{
return container_of(panel, struct panel_info, base);
}
static void disable_gpios(struct panel_info *pinfo)
{
gpiod_set_value(pinfo->enable_gpio, 0 );
gpiod_set_value(pinfo->pp33_gpio, 0 );
gpiod_set_value(pinfo->pp18_gpio, 0 );
}
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;
for (i = 0 ; i < pinfo->desc->on_cmds_num; i++) {
err = mipi_dsi_dcs_write_buffer(pinfo->link, &cmds[i],
sizeof (struct panel_cmd));
if (err < 0 )
return err;
}
return 0 ;
}
static int boe_panel_disable(struct drm_panel *panel)
{
struct panel_info *pinfo = to_panel_info(panel);
int err;
err = mipi_dsi_dcs_set_display_off(pinfo->link);
if (err < 0 ) {
dev_err(panel->dev, "failed to set display off: %d\n" , err);
return err;
}
return 0 ;
}
static int boe_panel_unprepare(struct drm_panel *panel)
{
struct panel_info *pinfo = to_panel_info(panel);
int err;
err = mipi_dsi_dcs_set_display_off(pinfo->link);
if (err < 0 )
dev_err(panel->dev, "failed to set display off: %d\n" , err);
err = mipi_dsi_dcs_enter_sleep_mode(pinfo->link);
if (err < 0 )
dev_err(panel->dev, "failed to enter sleep mode: %d\n" , err);
/* sleep_mode_delay: 1ms - 2ms */
usleep_range(1000 , 2000 );
disable_gpios(pinfo);
return 0 ;
}
static int boe_panel_prepare(struct drm_panel *panel)
{
struct panel_info *pinfo = to_panel_info(panel);
int err;
gpiod_set_value(pinfo->pp18_gpio, 1 );
/* T1: 5ms - 6ms */
usleep_range(5000 , 6000 );
gpiod_set_value(pinfo->pp33_gpio, 1 );
/* reset sequence */
/* T2: 14ms - 15ms */
usleep_range(14000 , 15000 );
gpiod_set_value(pinfo->enable_gpio, 1 );
/* T3: 1ms - 2ms */
usleep_range(1000 , 2000 );
gpiod_set_value(pinfo->enable_gpio, 0 );
/* T4: 1ms - 2ms */
usleep_range(1000 , 2000 );
gpiod_set_value(pinfo->enable_gpio, 1 );
/* T5: 5ms - 6ms */
usleep_range(5000 , 6000 );
/* send init code */
err = send_mipi_cmds(panel, pinfo->desc->on_cmds);
if (err < 0 ) {
dev_err(panel->dev, "failed to send DCS Init Code: %d\n" , err);
goto poweroff;
}
err = mipi_dsi_dcs_exit_sleep_mode(pinfo->link);
if (err < 0 ) {
dev_err(panel->dev, "failed to exit sleep mode: %d\n" , err);
goto poweroff;
}
/* T6: 120ms - 121ms */
usleep_range(120000 , 121000 );
err = mipi_dsi_dcs_set_display_on(pinfo->link);
if (err < 0 ) {
dev_err(panel->dev, "failed to set display on: %d\n" , err);
goto poweroff;
}
/* T7: 20ms - 21ms */
usleep_range(20000 , 21000 );
return 0 ;
poweroff:
disable_gpios(pinfo);
return err;
}
static int boe_panel_enable(struct drm_panel *panel)
{
struct panel_info *pinfo = to_panel_info(panel);
int ret;
usleep_range(120000 , 121000 );
ret = mipi_dsi_dcs_set_display_on(pinfo->link);
if (ret < 0 ) {
dev_err(panel->dev, "failed to set display on: %d\n" , ret);
return ret;
}
return 0 ;
}
static int boe_panel_get_modes(struct drm_panel *panel,
struct drm_connector *connector)
{
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(connector->dev, m);
if (!mode) {
dev_err(pinfo->base.dev, "failed to add mode %ux%u@%u\n" ,
m->hdisplay, m->vdisplay, drm_mode_vrefresh(m));
return -ENOMEM;
}
drm_mode_set_name(mode);
drm_mode_probed_add(connector, mode);
connector->display_info.width_mm = pinfo->desc->width_mm;
connector->display_info.height_mm = pinfo->desc->height_mm;
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 ,
};
/* 8 inch */
static const struct panel_cmd boe_himax8279d8p_on_cmds[] = {
{ 0 xB0, 0 x05 },
{ 0 xB1, 0 xE5 },
{ 0 xB3, 0 x52 },
{ 0 xC0, 0 x00 },
{ 0 xC2, 0 x57 },
{ 0 xD9, 0 x85 },
{ 0 xB0, 0 x01 },
{ 0 xC8, 0 x00 },
{ 0 xC9, 0 x00 },
{ 0 xCC, 0 x26 },
{ 0 xCD, 0 x26 },
{ 0 xDC, 0 x00 },
{ 0 xDD, 0 x00 },
{ 0 xE0, 0 x26 },
{ 0 xE1, 0 x26 },
{ 0 xB0, 0 x03 },
{ 0 xC3, 0 x2A },
{ 0 xE7, 0 x2A },
{ 0 xC5, 0 x2A },
{ 0 xDE, 0 x2A },
{ 0 xBC, 0 x02 },
{ 0 xCB, 0 x02 },
{ 0 xB0, 0 x00 },
{ 0 xB6, 0 x03 },
{ 0 xBA, 0 x8B },
{ 0 xBF, 0 x15 },
{ 0 xC0, 0 x18 },
{ 0 xC2, 0 x14 },
{ 0 xC3, 0 x02 },
{ 0 xC4, 0 x14 },
{ 0 xC5, 0 x02 },
{ 0 xCC, 0 x0A },
{ 0 xB0, 0 x06 },
{ 0 xC0, 0 xA5 },
{ 0 xD5, 0 x20 },
{ 0 xC0, 0 x00 },
{ 0 xB0, 0 x02 },
{ 0 xC0, 0 x00 },
{ 0 xC1, 0 x02 },
{ 0 xC2, 0 x06 },
{ 0 xC3, 0 x16 },
{ 0 xC4, 0 x0E },
{ 0 xC5, 0 x18 },
{ 0 xC6, 0 x26 },
{ 0 xC7, 0 x32 },
{ 0 xC8, 0 x3F },
{ 0 xC9, 0 x3F },
{ 0 xCA, 0 x3F },
{ 0 xCB, 0 x3F },
{ 0 xCC, 0 x3D },
{ 0 xCD, 0 x2F },
{ 0 xCE, 0 x2F },
{ 0 xCF, 0 x2F },
{ 0 xD0, 0 x07 },
{ 0 xD2, 0 x00 },
{ 0 xD3, 0 x02 },
{ 0 xD4, 0 x06 },
{ 0 xD5, 0 x12 },
{ 0 xD6, 0 x0A },
{ 0 xD7, 0 x14 },
{ 0 xD8, 0 x22 },
{ 0 xD9, 0 x2E },
{ 0 xDA, 0 x3D },
{ 0 xDB, 0 x3F },
{ 0 xDC, 0 x3F },
{ 0 xDD, 0 x3F },
{ 0 xDE, 0 x3D },
{ 0 xDF, 0 x2F },
{ 0 xE0, 0 x2F },
{ 0 xE1, 0 x2F },
{ 0 xE2, 0 x07 },
{ 0 xB0, 0 x07 },
{ 0 xB1, 0 x18 },
{ 0 xB2, 0 x19 },
{ 0 xB3, 0 x2E },
{ 0 xB4, 0 x52 },
{ 0 xB5, 0 x72 },
{ 0 xB6, 0 x8C },
{ 0 xB7, 0 xBD },
{ 0 xB8, 0 xEB },
{ 0 xB9, 0 x47 },
{ 0 xBA, 0 x96 },
{ 0 xBB, 0 x1E },
{ 0 xBC, 0 x90 },
{ 0 xBD, 0 x93 },
{ 0 xBE, 0 xFA },
{ 0 xBF, 0 x56 },
{ 0 xC0, 0 x8C },
{ 0 xC1, 0 xB7 },
{ 0 xC2, 0 xCC },
{ 0 xC3, 0 xDF },
{ 0 xC4, 0 xE8 },
{ 0 xC5, 0 xF0 },
{ 0 xC6, 0 xF8 },
{ 0 xC7, 0 xFA },
{ 0 xC8, 0 xFC },
{ 0 xC9, 0 x00 },
{ 0 xCA, 0 x00 },
{ 0 xCB, 0 x5A },
{ 0 xCC, 0 xAF },
{ 0 xCD, 0 xFF },
{ 0 xCE, 0 xFF },
{ 0 xB0, 0 x08 },
{ 0 xB1, 0 x04 },
{ 0 xB2, 0 x15 },
{ 0 xB3, 0 x2D },
{ 0 xB4, 0 x51 },
{ 0 xB5, 0 x72 },
{ 0 xB6, 0 x8D },
{ 0 xB7, 0 xBE },
{ 0 xB8, 0 xED },
{ 0 xB9, 0 x4A },
{ 0 xBA, 0 x9A },
{ 0 xBB, 0 x23 },
{ 0 xBC, 0 x95 },
{ 0 xBD, 0 x98 },
{ 0 xBE, 0 xFF },
{ 0 xBF, 0 x59 },
{ 0 xC0, 0 x8E },
{ 0 xC1, 0 xB9 },
{ 0 xC2, 0 xCD },
{ 0 xC3, 0 xDF },
{ 0 xC4, 0 xE8 },
{ 0 xC5, 0 xF0 },
{ 0 xC6, 0 xF8 },
{ 0 xC7, 0 xFA },
{ 0 xC8, 0 xFC },
{ 0 xC9, 0 x00 },
{ 0 xCA, 0 x00 },
{ 0 xCB, 0 x5A },
{ 0 xCC, 0 xAF },
{ 0 xCD, 0 xFF },
{ 0 xCE, 0 xFF },
{ 0 xB0, 0 x09 },
{ 0 xB1, 0 x04 },
{ 0 xB2, 0 x2C },
{ 0 xB3, 0 x36 },
{ 0 xB4, 0 x53 },
{ 0 xB5, 0 x73 },
{ 0 xB6, 0 x8E },
{ 0 xB7, 0 xC0 },
{ 0 xB8, 0 xEF },
{ 0 xB9, 0 x4C },
{ 0 xBA, 0 x9D },
{ 0 xBB, 0 x25 },
{ 0 xBC, 0 x96 },
{ 0 xBD, 0 x9A },
{ 0 xBE, 0 x01 },
{ 0 xBF, 0 x59 },
{ 0 xC0, 0 x8E },
{ 0 xC1, 0 xB9 },
{ 0 xC2, 0 xCD },
{ 0 xC3, 0 xDF },
{ 0 xC4, 0 xE8 },
{ 0 xC5, 0 xF0 },
{ 0 xC6, 0 xF8 },
{ 0 xC7, 0 xFA },
{ 0 xC8, 0 xFC },
{ 0 xC9, 0 x00 },
{ 0 xCA, 0 x00 },
{ 0 xCB, 0 x5A },
{ 0 xCC, 0 xBF },
{ 0 xCD, 0 xFF },
{ 0 xCE, 0 xFF },
{ 0 xB0, 0 x0A },
{ 0 xB1, 0 x18 },
{ 0 xB2, 0 x19 },
{ 0 xB3, 0 x2E },
{ 0 xB4, 0 x52 },
{ 0 xB5, 0 x72 },
{ 0 xB6, 0 x8C },
{ 0 xB7, 0 xBD },
{ 0 xB8, 0 xEB },
{ 0 xB9, 0 x47 },
{ 0 xBA, 0 x96 },
{ 0 xBB, 0 x1E },
{ 0 xBC, 0 x90 },
{ 0 xBD, 0 x93 },
{ 0 xBE, 0 xFA },
{ 0 xBF, 0 x56 },
{ 0 xC0, 0 x8C },
{ 0 xC1, 0 xB7 },
{ 0 xC2, 0 xCC },
{ 0 xC3, 0 xDF },
{ 0 xC4, 0 xE8 },
{ 0 xC5, 0 xF0 },
{ 0 xC6, 0 xF8 },
{ 0 xC7, 0 xFA },
{ 0 xC8, 0 xFC },
{ 0 xC9, 0 x00 },
{ 0 xCA, 0 x00 },
{ 0 xCB, 0 x5A },
{ 0 xCC, 0 xAF },
{ 0 xCD, 0 xFF },
{ 0 xCE, 0 xFF },
{ 0 xB0, 0 x0B },
{ 0 xB1, 0 x04 },
{ 0 xB2, 0 x15 },
{ 0 xB3, 0 x2D },
{ 0 xB4, 0 x51 },
{ 0 xB5, 0 x72 },
{ 0 xB6, 0 x8D },
{ 0 xB7, 0 xBE },
{ 0 xB8, 0 xED },
{ 0 xB9, 0 x4A },
{ 0 xBA, 0 x9A },
{ 0 xBB, 0 x23 },
{ 0 xBC, 0 x95 },
{ 0 xBD, 0 x98 },
{ 0 xBE, 0 xFF },
{ 0 xBF, 0 x59 },
{ 0 xC0, 0 x8E },
{ 0 xC1, 0 xB9 },
{ 0 xC2, 0 xCD },
{ 0 xC3, 0 xDF },
{ 0 xC4, 0 xE8 },
{ 0 xC5, 0 xF0 },
{ 0 xC6, 0 xF8 },
{ 0 xC7, 0 xFA },
{ 0 xC8, 0 xFC },
{ 0 xC9, 0 x00 },
{ 0 xCA, 0 x00 },
{ 0 xCB, 0 x5A },
{ 0 xCC, 0 xAF },
{ 0 xCD, 0 xFF },
{ 0 xCE, 0 xFF },
{ 0 xB0, 0 x0C },
{ 0 xB1, 0 x04 },
{ 0 xB2, 0 x2C },
{ 0 xB3, 0 x36 },
{ 0 xB4, 0 x53 },
{ 0 xB5, 0 x73 },
{ 0 xB6, 0 x8E },
{ 0 xB7, 0 xC0 },
{ 0 xB8, 0 xEF },
{ 0 xB9, 0 x4C },
{ 0 xBA, 0 x9D },
{ 0 xBB, 0 x25 },
{ 0 xBC, 0 x96 },
{ 0 xBD, 0 x9A },
{ 0 xBE, 0 x01 },
{ 0 xBF, 0 x59 },
{ 0 xC0, 0 x8E },
{ 0 xC1, 0 xB9 },
{ 0 xC2, 0 xCD },
{ 0 xC3, 0 xDF },
{ 0 xC4, 0 xE8 },
{ 0 xC5, 0 xF0 },
{ 0 xC6, 0 xF8 },
{ 0 xC7, 0 xFA },
{ 0 xC8, 0 xFC },
{ 0 xC9, 0 x00 },
{ 0 xCA, 0 x00 },
{ 0 xCB, 0 x5A },
{ 0 xCC, 0 xBF },
{ 0 xCD, 0 xFF },
{ 0 xCE, 0 xFF },
{ 0 xB0, 0 x04 },
{ 0 xB5, 0 x02 },
{ 0 xB6, 0 x01 },
};
static const struct panel_desc boe_himax8279d8p_panel_desc = {
.display_mode = &default_display_mode,
.bpc = 8 ,
.width_mm = 107 ,
.height_mm = 172 ,
.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,
.on_cmds_num = 260 ,
};
/* 10 inch */
static const struct panel_cmd boe_himax8279d10p_on_cmds[] = {
{ 0 xB0, 0 x05 },
{ 0 xB1, 0 xE5 },
{ 0 xB3, 0 x52 },
{ 0 xB0, 0 x00 },
{ 0 xB6, 0 x03 },
{ 0 xBA, 0 x8B },
{ 0 xBF, 0 x1A },
{ 0 xC0, 0 x0F },
{ 0 xC2, 0 x0C },
{ 0 xC3, 0 x02 },
{ 0 xC4, 0 x0C },
{ 0 xC5, 0 x02 },
{ 0 xB0, 0 x01 },
{ 0 xE0, 0 x26 },
{ 0 xE1, 0 x26 },
{ 0 xDC, 0 x00 },
{ 0 xDD, 0 x00 },
{ 0 xCC, 0 x26 },
{ 0 xCD, 0 x26 },
{ 0 xC8, 0 x00 },
{ 0 xC9, 0 x00 },
{ 0 xD2, 0 x03 },
{ 0 xD3, 0 x03 },
{ 0 xE6, 0 x04 },
{ 0 xE7, 0 x04 },
{ 0 xC4, 0 x09 },
{ 0 xC5, 0 x09 },
{ 0 xD8, 0 x0A },
{ 0 xD9, 0 x0A },
{ 0 xC2, 0 x0B },
{ 0 xC3, 0 x0B },
{ 0 xD6, 0 x0C },
{ 0 xD7, 0 x0C },
{ 0 xC0, 0 x05 },
{ 0 xC1, 0 x05 },
{ 0 xD4, 0 x06 },
{ 0 xD5, 0 x06 },
{ 0 xCA, 0 x07 },
{ 0 xCB, 0 x07 },
{ 0 xDE, 0 x08 },
{ 0 xDF, 0 x08 },
{ 0 xB0, 0 x02 },
{ 0 xC0, 0 x00 },
{ 0 xC1, 0 x0D },
{ 0 xC2, 0 x17 },
{ 0 xC3, 0 x26 },
{ 0 xC4, 0 x31 },
{ 0 xC5, 0 x1C },
{ 0 xC6, 0 x2C },
{ 0 xC7, 0 x33 },
{ 0 xC8, 0 x31 },
{ 0 xC9, 0 x37 },
{ 0 xCA, 0 x37 },
{ 0 xCB, 0 x37 },
{ 0 xCC, 0 x39 },
{ 0 xCD, 0 x2E },
{ 0 xCE, 0 x2F },
{ 0 xCF, 0 x2F },
{ 0 xD0, 0 x07 },
{ 0 xD2, 0 x00 },
{ 0 xD3, 0 x0D },
{ 0 xD4, 0 x17 },
{ 0 xD5, 0 x26 },
{ 0 xD6, 0 x31 },
{ 0 xD7, 0 x3F },
{ 0 xD8, 0 x3F },
{ 0 xD9, 0 x3F },
{ 0 xDA, 0 x3F },
{ 0 xDB, 0 x37 },
{ 0 xDC, 0 x37 },
{ 0 xDD, 0 x37 },
{ 0 xDE, 0 x39 },
{ 0 xDF, 0 x2E },
{ 0 xE0, 0 x2F },
{ 0 xE1, 0 x2F },
{ 0 xE2, 0 x07 },
{ 0 xB0, 0 x03 },
{ 0 xC8, 0 x0B },
{ 0 xC9, 0 x07 },
{ 0 xC3, 0 x00 },
{ 0 xE7, 0 x00 },
{ 0 xC5, 0 x2A },
{ 0 xDE, 0 x2A },
{ 0 xCA, 0 x43 },
{ 0 xC9, 0 x07 },
{ 0 xE4, 0 xC0 },
{ 0 xE5, 0 x0D },
{ 0 xCB, 0 x01 },
{ 0 xBC, 0 x01 },
{ 0 xB0, 0 x06 },
{ 0 xB8, 0 xA5 },
{ 0 xC0, 0 xA5 },
{ 0 xC7, 0 x0F },
{ 0 xD5, 0 x32 },
{ 0 xB8, 0 x00 },
{ 0 xC0, 0 x00 },
{ 0 xBC, 0 x00 },
{ 0 xB0, 0 x07 },
{ 0 xB1, 0 x00 },
{ 0 xB2, 0 x05 },
{ 0 xB3, 0 x10 },
{ 0 xB4, 0 x22 },
{ 0 xB5, 0 x36 },
{ 0 xB6, 0 x4A },
{ 0 xB7, 0 x6C },
{ 0 xB8, 0 x9A },
{ 0 xB9, 0 xD7 },
{ 0 xBA, 0 x17 },
{ 0 xBB, 0 x92 },
{ 0 xBC, 0 x15 },
{ 0 xBD, 0 x18 },
{ 0 xBE, 0 x8C },
{ 0 xBF, 0 x00 },
{ 0 xC0, 0 x3A },
{ 0 xC1, 0 x72 },
{ 0 xC2, 0 x8C },
{ 0 xC3, 0 xA5 },
{ 0 xC4, 0 xB1 },
{ 0 xC5, 0 xBE },
{ 0 xC6, 0 xCA },
{ 0 xC7, 0 xD1 },
{ 0 xC8, 0 xD4 },
{ 0 xC9, 0 x00 },
{ 0 xCA, 0 x00 },
{ 0 xCB, 0 x16 },
{ 0 xCC, 0 xAF },
{ 0 xCD, 0 xFF },
{ 0 xCE, 0 xFF },
{ 0 xB0, 0 x08 },
{ 0 xB1, 0 x04 },
{ 0 xB2, 0 x05 },
{ 0 xB3, 0 x11 },
{ 0 xB4, 0 x24 },
{ 0 xB5, 0 x39 },
{ 0 xB6, 0 x4E },
{ 0 xB7, 0 x72 },
{ 0 xB8, 0 xA3 },
{ 0 xB9, 0 xE1 },
{ 0 xBA, 0 x25 },
{ 0 xBB, 0 xA8 },
{ 0 xBC, 0 x2E },
{ 0 xBD, 0 x32 },
{ 0 xBE, 0 xAD },
{ 0 xBF, 0 x28 },
{ 0 xC0, 0 x63 },
{ 0 xC1, 0 x9B },
{ 0 xC2, 0 xB5 },
{ 0 xC3, 0 xCF },
{ 0 xC4, 0 xDB },
{ 0 xC5, 0 xE8 },
{ 0 xC6, 0 xF5 },
{ 0 xC7, 0 xFA },
{ 0 xC8, 0 xFC },
{ 0 xC9, 0 x00 },
{ 0 xCA, 0 x00 },
{ 0 xCB, 0 x16 },
{ 0 xCC, 0 xAF },
{ 0 xCD, 0 xFF },
{ 0 xCE, 0 xFF },
{ 0 xB0, 0 x09 },
{ 0 xB1, 0 x04 },
{ 0 xB2, 0 x04 },
{ 0 xB3, 0 x0F },
{ 0 xB4, 0 x22 },
{ 0 xB5, 0 x37 },
{ 0 xB6, 0 x4D },
{ 0 xB7, 0 x71 },
{ 0 xB8, 0 xA2 },
{ 0 xB9, 0 xE1 },
{ 0 xBA, 0 x26 },
{ 0 xBB, 0 xA9 },
{ 0 xBC, 0 x2F },
{ 0 xBD, 0 x33 },
{ 0 xBE, 0 xAC },
{ 0 xBF, 0 x24 },
{ 0 xC0, 0 x5D },
{ 0 xC1, 0 x94 },
{ 0 xC2, 0 xAC },
{ 0 xC3, 0 xC5 },
{ 0 xC4, 0 xD1 },
{ 0 xC5, 0 xDC },
{ 0 xC6, 0 xE8 },
{ 0 xC7, 0 xED },
{ 0 xC8, 0 xF0 },
{ 0 xC9, 0 x00 },
{ 0 xCA, 0 x00 },
{ 0 xCB, 0 x16 },
{ 0 xCC, 0 xAF },
{ 0 xCD, 0 xFF },
{ 0 xCE, 0 xFF },
{ 0 xB0, 0 x0A },
{ 0 xB1, 0 x00 },
{ 0 xB2, 0 x05 },
{ 0 xB3, 0 x10 },
{ 0 xB4, 0 x22 },
{ 0 xB5, 0 x36 },
{ 0 xB6, 0 x4A },
{ 0 xB7, 0 x6C },
{ 0 xB8, 0 x9A },
{ 0 xB9, 0 xD7 },
{ 0 xBA, 0 x17 },
{ 0 xBB, 0 x92 },
{ 0 xBC, 0 x15 },
{ 0 xBD, 0 x18 },
{ 0 xBE, 0 x8C },
{ 0 xBF, 0 x00 },
{ 0 xC0, 0 x3A },
{ 0 xC1, 0 x72 },
{ 0 xC2, 0 x8C },
{ 0 xC3, 0 xA5 },
{ 0 xC4, 0 xB1 },
{ 0 xC5, 0 xBE },
{ 0 xC6, 0 xCA },
{ 0 xC7, 0 xD1 },
{ 0 xC8, 0 xD4 },
{ 0 xC9, 0 x00 },
{ 0 xCA, 0 x00 },
{ 0 xCB, 0 x16 },
{ 0 xCC, 0 xAF },
{ 0 xCD, 0 xFF },
{ 0 xCE, 0 xFF },
{ 0 xB0, 0 x0B },
{ 0 xB1, 0 x04 },
{ 0 xB2, 0 x05 },
{ 0 xB3, 0 x11 },
{ 0 xB4, 0 x24 },
{ 0 xB5, 0 x39 },
{ 0 xB6, 0 x4E },
{ 0 xB7, 0 x72 },
{ 0 xB8, 0 xA3 },
{ 0 xB9, 0 xE1 },
{ 0 xBA, 0 x25 },
{ 0 xBB, 0 xA8 },
{ 0 xBC, 0 x2E },
{ 0 xBD, 0 x32 },
{ 0 xBE, 0 xAD },
{ 0 xBF, 0 x28 },
{ 0 xC0, 0 x63 },
{ 0 xC1, 0 x9B },
{ 0 xC2, 0 xB5 },
{ 0 xC3, 0 xCF },
{ 0 xC4, 0 xDB },
{ 0 xC5, 0 xE8 },
{ 0 xC6, 0 xF5 },
{ 0 xC7, 0 xFA },
{ 0 xC8, 0 xFC },
{ 0 xC9, 0 x00 },
{ 0 xCA, 0 x00 },
{ 0 xCB, 0 x16 },
{ 0 xCC, 0 xAF },
{ 0 xCD, 0 xFF },
{ 0 xCE, 0 xFF },
{ 0 xB0, 0 x0C },
{ 0 xB1, 0 x04 },
{ 0 xB2, 0 x04 },
{ 0 xB3, 0 x0F },
{ 0 xB4, 0 x22 },
{ 0 xB5, 0 x37 },
{ 0 xB6, 0 x4D },
{ 0 xB7, 0 x71 },
{ 0 xB8, 0 xA2 },
{ 0 xB9, 0 xE1 },
{ 0 xBA, 0 x26 },
{ 0 xBB, 0 xA9 },
{ 0 xBC, 0 x2F },
{ 0 xBD, 0 x33 },
{ 0 xBE, 0 xAC },
{ 0 xBF, 0 x24 },
{ 0 xC0, 0 x5D },
{ 0 xC1, 0 x94 },
{ 0 xC2, 0 xAC },
{ 0 xC3, 0 xC5 },
{ 0 xC4, 0 xD1 },
{ 0 xC5, 0 xDC },
{ 0 xC6, 0 xE8 },
{ 0 xC7, 0 xED },
{ 0 xC8, 0 xF0 },
{ 0 xC9, 0 x00 },
{ 0 xCA, 0 x00 },
{ 0 xCB, 0 x16 },
{ 0 xCC, 0 xAF },
{ 0 xCD, 0 xFF },
{ 0 xCE, 0 xFF },
};
static const struct panel_desc boe_himax8279d10p_panel_desc = {
.display_mode = &default_display_mode,
.bpc = 8 ,
.width_mm = 135 ,
.height_mm = 216 ,
.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,
.on_cmds_num = 283 ,
};
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(dev, "pp18" , GPIOD_OUT_HIGH);
if (IS_ERR(pinfo->pp18_gpio)) {
return dev_err_probe(dev, PTR_ERR(pinfo->pp18_gpio),
"failed to get pp18 gpio\n" );
}
pinfo->pp33_gpio = devm_gpiod_get(dev, "pp33" , GPIOD_OUT_HIGH);
if (IS_ERR(pinfo->pp33_gpio)) {
return dev_err_probe(dev, PTR_ERR(pinfo->pp33_gpio),
"failed to get pp33 gpio\n" );
}
pinfo->enable_gpio = devm_gpiod_get(dev, "enable" , GPIOD_OUT_HIGH);
if (IS_ERR(pinfo->enable_gpio)) {
return dev_err_probe(dev, PTR_ERR(pinfo->enable_gpio),
"failed to get enable gpio\n" );
}
ret = drm_panel_of_backlight(&pinfo->base);
if (ret)
return ret;
drm_panel_add(&pinfo->base);
return 0 ;
}
static int panel_probe(struct mipi_dsi_device *dsi)
{
struct panel_info *pinfo;
const struct panel_desc *desc;
int err;
pinfo = devm_drm_panel_alloc(&dsi->dev, __typeof(*pinfo), base,
&panel_funcs, DRM_MODE_CONNECTOR_DSI);
if (IS_ERR(pinfo))
return PTR_ERR(pinfo);
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;
err = mipi_dsi_attach(dsi);
if (err < 0 )
drm_panel_remove(&pinfo->base);
return err;
}
static void panel_remove(struct mipi_dsi_device *dsi)
{
struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
int err;
err = mipi_dsi_detach(dsi);
if (err < 0 )
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n" , err);
drm_panel_remove(&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,
};
module_mipi_dsi_driver(panel_driver);
MODULE_AUTHOR("Jerry Han <jerry.han.hq@gmail.com>" );
MODULE_DESCRIPTION("Boe Himax8279d driver" );
MODULE_LICENSE("GPL v2" );
Messung V0.5 in Prozent C=97 H=96 G=96