linux/drivers/gpu/drm/panel/panel-boe-himax8279d.c
Rob Herring 722d4f06e5 drm: Explicitly include correct DT includes
The DT of_device.h and of_platform.h date back to the separate
of_platform_bus_type before it as merged into the regular platform bus.
As part of that merge prepping Arm DT support 13 years ago, they
"temporarily" include each other. They also include platform_device.h
and of.h. As a result, there's a pretty much random mix of those include
files used throughout the tree. In order to detangle these headers and
replace the implicit includes with struct declarations, users need to
explicitly include the correct includes.

Signed-off-by: Rob Herring <robh@kernel.org>
Acked-by: Sam Ravnborg <sam@ravnborg.org>
Reviewed-by: Steven Price <steven.price@arm.com>
Acked-by: Liviu Dudau <liviu.dudau@arm.com>
Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Acked-by: Robert Foss <rfoss@kernel.org>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230714174545.4056287-1-robh@kernel.org
2023-07-21 09:12:43 +02:00

963 lines
18 KiB
C

// 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;
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 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;
if (!pinfo->enabled)
return 0;
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;
}
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;
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);
pinfo->prepared = false;
return 0;
}
static int boe_panel_prepare(struct drm_panel *panel)
{
struct panel_info *pinfo = to_panel_info(panel);
int err;
if (pinfo->prepared)
return 0;
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);
pinfo->prepared = true;
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;
if (pinfo->enabled)
return 0;
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;
}
pinfo->enabled = true;
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[] = {
{ 0xB0, 0x05 },
{ 0xB1, 0xE5 },
{ 0xB3, 0x52 },
{ 0xC0, 0x00 },
{ 0xC2, 0x57 },
{ 0xD9, 0x85 },
{ 0xB0, 0x01 },
{ 0xC8, 0x00 },
{ 0xC9, 0x00 },
{ 0xCC, 0x26 },
{ 0xCD, 0x26 },
{ 0xDC, 0x00 },
{ 0xDD, 0x00 },
{ 0xE0, 0x26 },
{ 0xE1, 0x26 },
{ 0xB0, 0x03 },
{ 0xC3, 0x2A },
{ 0xE7, 0x2A },
{ 0xC5, 0x2A },
{ 0xDE, 0x2A },
{ 0xBC, 0x02 },
{ 0xCB, 0x02 },
{ 0xB0, 0x00 },
{ 0xB6, 0x03 },
{ 0xBA, 0x8B },
{ 0xBF, 0x15 },
{ 0xC0, 0x18 },
{ 0xC2, 0x14 },
{ 0xC3, 0x02 },
{ 0xC4, 0x14 },
{ 0xC5, 0x02 },
{ 0xCC, 0x0A },
{ 0xB0, 0x06 },
{ 0xC0, 0xA5 },
{ 0xD5, 0x20 },
{ 0xC0, 0x00 },
{ 0xB0, 0x02 },
{ 0xC0, 0x00 },
{ 0xC1, 0x02 },
{ 0xC2, 0x06 },
{ 0xC3, 0x16 },
{ 0xC4, 0x0E },
{ 0xC5, 0x18 },
{ 0xC6, 0x26 },
{ 0xC7, 0x32 },
{ 0xC8, 0x3F },
{ 0xC9, 0x3F },
{ 0xCA, 0x3F },
{ 0xCB, 0x3F },
{ 0xCC, 0x3D },
{ 0xCD, 0x2F },
{ 0xCE, 0x2F },
{ 0xCF, 0x2F },
{ 0xD0, 0x07 },
{ 0xD2, 0x00 },
{ 0xD3, 0x02 },
{ 0xD4, 0x06 },
{ 0xD5, 0x12 },
{ 0xD6, 0x0A },
{ 0xD7, 0x14 },
{ 0xD8, 0x22 },
{ 0xD9, 0x2E },
{ 0xDA, 0x3D },
{ 0xDB, 0x3F },
{ 0xDC, 0x3F },
{ 0xDD, 0x3F },
{ 0xDE, 0x3D },
{ 0xDF, 0x2F },
{ 0xE0, 0x2F },
{ 0xE1, 0x2F },
{ 0xE2, 0x07 },
{ 0xB0, 0x07 },
{ 0xB1, 0x18 },
{ 0xB2, 0x19 },
{ 0xB3, 0x2E },
{ 0xB4, 0x52 },
{ 0xB5, 0x72 },
{ 0xB6, 0x8C },
{ 0xB7, 0xBD },
{ 0xB8, 0xEB },
{ 0xB9, 0x47 },
{ 0xBA, 0x96 },
{ 0xBB, 0x1E },
{ 0xBC, 0x90 },
{ 0xBD, 0x93 },
{ 0xBE, 0xFA },
{ 0xBF, 0x56 },
{ 0xC0, 0x8C },
{ 0xC1, 0xB7 },
{ 0xC2, 0xCC },
{ 0xC3, 0xDF },
{ 0xC4, 0xE8 },
{ 0xC5, 0xF0 },
{ 0xC6, 0xF8 },
{ 0xC7, 0xFA },
{ 0xC8, 0xFC },
{ 0xC9, 0x00 },
{ 0xCA, 0x00 },
{ 0xCB, 0x5A },
{ 0xCC, 0xAF },
{ 0xCD, 0xFF },
{ 0xCE, 0xFF },
{ 0xB0, 0x08 },
{ 0xB1, 0x04 },
{ 0xB2, 0x15 },
{ 0xB3, 0x2D },
{ 0xB4, 0x51 },
{ 0xB5, 0x72 },
{ 0xB6, 0x8D },
{ 0xB7, 0xBE },
{ 0xB8, 0xED },
{ 0xB9, 0x4A },
{ 0xBA, 0x9A },
{ 0xBB, 0x23 },
{ 0xBC, 0x95 },
{ 0xBD, 0x98 },
{ 0xBE, 0xFF },
{ 0xBF, 0x59 },
{ 0xC0, 0x8E },
{ 0xC1, 0xB9 },
{ 0xC2, 0xCD },
{ 0xC3, 0xDF },
{ 0xC4, 0xE8 },
{ 0xC5, 0xF0 },
{ 0xC6, 0xF8 },
{ 0xC7, 0xFA },
{ 0xC8, 0xFC },
{ 0xC9, 0x00 },
{ 0xCA, 0x00 },
{ 0xCB, 0x5A },
{ 0xCC, 0xAF },
{ 0xCD, 0xFF },
{ 0xCE, 0xFF },
{ 0xB0, 0x09 },
{ 0xB1, 0x04 },
{ 0xB2, 0x2C },
{ 0xB3, 0x36 },
{ 0xB4, 0x53 },
{ 0xB5, 0x73 },
{ 0xB6, 0x8E },
{ 0xB7, 0xC0 },
{ 0xB8, 0xEF },
{ 0xB9, 0x4C },
{ 0xBA, 0x9D },
{ 0xBB, 0x25 },
{ 0xBC, 0x96 },
{ 0xBD, 0x9A },
{ 0xBE, 0x01 },
{ 0xBF, 0x59 },
{ 0xC0, 0x8E },
{ 0xC1, 0xB9 },
{ 0xC2, 0xCD },
{ 0xC3, 0xDF },
{ 0xC4, 0xE8 },
{ 0xC5, 0xF0 },
{ 0xC6, 0xF8 },
{ 0xC7, 0xFA },
{ 0xC8, 0xFC },
{ 0xC9, 0x00 },
{ 0xCA, 0x00 },
{ 0xCB, 0x5A },
{ 0xCC, 0xBF },
{ 0xCD, 0xFF },
{ 0xCE, 0xFF },
{ 0xB0, 0x0A },
{ 0xB1, 0x18 },
{ 0xB2, 0x19 },
{ 0xB3, 0x2E },
{ 0xB4, 0x52 },
{ 0xB5, 0x72 },
{ 0xB6, 0x8C },
{ 0xB7, 0xBD },
{ 0xB8, 0xEB },
{ 0xB9, 0x47 },
{ 0xBA, 0x96 },
{ 0xBB, 0x1E },
{ 0xBC, 0x90 },
{ 0xBD, 0x93 },
{ 0xBE, 0xFA },
{ 0xBF, 0x56 },
{ 0xC0, 0x8C },
{ 0xC1, 0xB7 },
{ 0xC2, 0xCC },
{ 0xC3, 0xDF },
{ 0xC4, 0xE8 },
{ 0xC5, 0xF0 },
{ 0xC6, 0xF8 },
{ 0xC7, 0xFA },
{ 0xC8, 0xFC },
{ 0xC9, 0x00 },
{ 0xCA, 0x00 },
{ 0xCB, 0x5A },
{ 0xCC, 0xAF },
{ 0xCD, 0xFF },
{ 0xCE, 0xFF },
{ 0xB0, 0x0B },
{ 0xB1, 0x04 },
{ 0xB2, 0x15 },
{ 0xB3, 0x2D },
{ 0xB4, 0x51 },
{ 0xB5, 0x72 },
{ 0xB6, 0x8D },
{ 0xB7, 0xBE },
{ 0xB8, 0xED },
{ 0xB9, 0x4A },
{ 0xBA, 0x9A },
{ 0xBB, 0x23 },
{ 0xBC, 0x95 },
{ 0xBD, 0x98 },
{ 0xBE, 0xFF },
{ 0xBF, 0x59 },
{ 0xC0, 0x8E },
{ 0xC1, 0xB9 },
{ 0xC2, 0xCD },
{ 0xC3, 0xDF },
{ 0xC4, 0xE8 },
{ 0xC5, 0xF0 },
{ 0xC6, 0xF8 },
{ 0xC7, 0xFA },
{ 0xC8, 0xFC },
{ 0xC9, 0x00 },
{ 0xCA, 0x00 },
{ 0xCB, 0x5A },
{ 0xCC, 0xAF },
{ 0xCD, 0xFF },
{ 0xCE, 0xFF },
{ 0xB0, 0x0C },
{ 0xB1, 0x04 },
{ 0xB2, 0x2C },
{ 0xB3, 0x36 },
{ 0xB4, 0x53 },
{ 0xB5, 0x73 },
{ 0xB6, 0x8E },
{ 0xB7, 0xC0 },
{ 0xB8, 0xEF },
{ 0xB9, 0x4C },
{ 0xBA, 0x9D },
{ 0xBB, 0x25 },
{ 0xBC, 0x96 },
{ 0xBD, 0x9A },
{ 0xBE, 0x01 },
{ 0xBF, 0x59 },
{ 0xC0, 0x8E },
{ 0xC1, 0xB9 },
{ 0xC2, 0xCD },
{ 0xC3, 0xDF },
{ 0xC4, 0xE8 },
{ 0xC5, 0xF0 },
{ 0xC6, 0xF8 },
{ 0xC7, 0xFA },
{ 0xC8, 0xFC },
{ 0xC9, 0x00 },
{ 0xCA, 0x00 },
{ 0xCB, 0x5A },
{ 0xCC, 0xBF },
{ 0xCD, 0xFF },
{ 0xCE, 0xFF },
{ 0xB0, 0x04 },
{ 0xB5, 0x02 },
{ 0xB6, 0x01 },
};
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[] = {
{ 0xB0, 0x05 },
{ 0xB1, 0xE5 },
{ 0xB3, 0x52 },
{ 0xB0, 0x00 },
{ 0xB6, 0x03 },
{ 0xBA, 0x8B },
{ 0xBF, 0x1A },
{ 0xC0, 0x0F },
{ 0xC2, 0x0C },
{ 0xC3, 0x02 },
{ 0xC4, 0x0C },
{ 0xC5, 0x02 },
{ 0xB0, 0x01 },
{ 0xE0, 0x26 },
{ 0xE1, 0x26 },
{ 0xDC, 0x00 },
{ 0xDD, 0x00 },
{ 0xCC, 0x26 },
{ 0xCD, 0x26 },
{ 0xC8, 0x00 },
{ 0xC9, 0x00 },
{ 0xD2, 0x03 },
{ 0xD3, 0x03 },
{ 0xE6, 0x04 },
{ 0xE7, 0x04 },
{ 0xC4, 0x09 },
{ 0xC5, 0x09 },
{ 0xD8, 0x0A },
{ 0xD9, 0x0A },
{ 0xC2, 0x0B },
{ 0xC3, 0x0B },
{ 0xD6, 0x0C },
{ 0xD7, 0x0C },
{ 0xC0, 0x05 },
{ 0xC1, 0x05 },
{ 0xD4, 0x06 },
{ 0xD5, 0x06 },
{ 0xCA, 0x07 },
{ 0xCB, 0x07 },
{ 0xDE, 0x08 },
{ 0xDF, 0x08 },
{ 0xB0, 0x02 },
{ 0xC0, 0x00 },
{ 0xC1, 0x0D },
{ 0xC2, 0x17 },
{ 0xC3, 0x26 },
{ 0xC4, 0x31 },
{ 0xC5, 0x1C },
{ 0xC6, 0x2C },
{ 0xC7, 0x33 },
{ 0xC8, 0x31 },
{ 0xC9, 0x37 },
{ 0xCA, 0x37 },
{ 0xCB, 0x37 },
{ 0xCC, 0x39 },
{ 0xCD, 0x2E },
{ 0xCE, 0x2F },
{ 0xCF, 0x2F },
{ 0xD0, 0x07 },
{ 0xD2, 0x00 },
{ 0xD3, 0x0D },
{ 0xD4, 0x17 },
{ 0xD5, 0x26 },
{ 0xD6, 0x31 },
{ 0xD7, 0x3F },
{ 0xD8, 0x3F },
{ 0xD9, 0x3F },
{ 0xDA, 0x3F },
{ 0xDB, 0x37 },
{ 0xDC, 0x37 },
{ 0xDD, 0x37 },
{ 0xDE, 0x39 },
{ 0xDF, 0x2E },
{ 0xE0, 0x2F },
{ 0xE1, 0x2F },
{ 0xE2, 0x07 },
{ 0xB0, 0x03 },
{ 0xC8, 0x0B },
{ 0xC9, 0x07 },
{ 0xC3, 0x00 },
{ 0xE7, 0x00 },
{ 0xC5, 0x2A },
{ 0xDE, 0x2A },
{ 0xCA, 0x43 },
{ 0xC9, 0x07 },
{ 0xE4, 0xC0 },
{ 0xE5, 0x0D },
{ 0xCB, 0x01 },
{ 0xBC, 0x01 },
{ 0xB0, 0x06 },
{ 0xB8, 0xA5 },
{ 0xC0, 0xA5 },
{ 0xC7, 0x0F },
{ 0xD5, 0x32 },
{ 0xB8, 0x00 },
{ 0xC0, 0x00 },
{ 0xBC, 0x00 },
{ 0xB0, 0x07 },
{ 0xB1, 0x00 },
{ 0xB2, 0x05 },
{ 0xB3, 0x10 },
{ 0xB4, 0x22 },
{ 0xB5, 0x36 },
{ 0xB6, 0x4A },
{ 0xB7, 0x6C },
{ 0xB8, 0x9A },
{ 0xB9, 0xD7 },
{ 0xBA, 0x17 },
{ 0xBB, 0x92 },
{ 0xBC, 0x15 },
{ 0xBD, 0x18 },
{ 0xBE, 0x8C },
{ 0xBF, 0x00 },
{ 0xC0, 0x3A },
{ 0xC1, 0x72 },
{ 0xC2, 0x8C },
{ 0xC3, 0xA5 },
{ 0xC4, 0xB1 },
{ 0xC5, 0xBE },
{ 0xC6, 0xCA },
{ 0xC7, 0xD1 },
{ 0xC8, 0xD4 },
{ 0xC9, 0x00 },
{ 0xCA, 0x00 },
{ 0xCB, 0x16 },
{ 0xCC, 0xAF },
{ 0xCD, 0xFF },
{ 0xCE, 0xFF },
{ 0xB0, 0x08 },
{ 0xB1, 0x04 },
{ 0xB2, 0x05 },
{ 0xB3, 0x11 },
{ 0xB4, 0x24 },
{ 0xB5, 0x39 },
{ 0xB6, 0x4E },
{ 0xB7, 0x72 },
{ 0xB8, 0xA3 },
{ 0xB9, 0xE1 },
{ 0xBA, 0x25 },
{ 0xBB, 0xA8 },
{ 0xBC, 0x2E },
{ 0xBD, 0x32 },
{ 0xBE, 0xAD },
{ 0xBF, 0x28 },
{ 0xC0, 0x63 },
{ 0xC1, 0x9B },
{ 0xC2, 0xB5 },
{ 0xC3, 0xCF },
{ 0xC4, 0xDB },
{ 0xC5, 0xE8 },
{ 0xC6, 0xF5 },
{ 0xC7, 0xFA },
{ 0xC8, 0xFC },
{ 0xC9, 0x00 },
{ 0xCA, 0x00 },
{ 0xCB, 0x16 },
{ 0xCC, 0xAF },
{ 0xCD, 0xFF },
{ 0xCE, 0xFF },
{ 0xB0, 0x09 },
{ 0xB1, 0x04 },
{ 0xB2, 0x04 },
{ 0xB3, 0x0F },
{ 0xB4, 0x22 },
{ 0xB5, 0x37 },
{ 0xB6, 0x4D },
{ 0xB7, 0x71 },
{ 0xB8, 0xA2 },
{ 0xB9, 0xE1 },
{ 0xBA, 0x26 },
{ 0xBB, 0xA9 },
{ 0xBC, 0x2F },
{ 0xBD, 0x33 },
{ 0xBE, 0xAC },
{ 0xBF, 0x24 },
{ 0xC0, 0x5D },
{ 0xC1, 0x94 },
{ 0xC2, 0xAC },
{ 0xC3, 0xC5 },
{ 0xC4, 0xD1 },
{ 0xC5, 0xDC },
{ 0xC6, 0xE8 },
{ 0xC7, 0xED },
{ 0xC8, 0xF0 },
{ 0xC9, 0x00 },
{ 0xCA, 0x00 },
{ 0xCB, 0x16 },
{ 0xCC, 0xAF },
{ 0xCD, 0xFF },
{ 0xCE, 0xFF },
{ 0xB0, 0x0A },
{ 0xB1, 0x00 },
{ 0xB2, 0x05 },
{ 0xB3, 0x10 },
{ 0xB4, 0x22 },
{ 0xB5, 0x36 },
{ 0xB6, 0x4A },
{ 0xB7, 0x6C },
{ 0xB8, 0x9A },
{ 0xB9, 0xD7 },
{ 0xBA, 0x17 },
{ 0xBB, 0x92 },
{ 0xBC, 0x15 },
{ 0xBD, 0x18 },
{ 0xBE, 0x8C },
{ 0xBF, 0x00 },
{ 0xC0, 0x3A },
{ 0xC1, 0x72 },
{ 0xC2, 0x8C },
{ 0xC3, 0xA5 },
{ 0xC4, 0xB1 },
{ 0xC5, 0xBE },
{ 0xC6, 0xCA },
{ 0xC7, 0xD1 },
{ 0xC8, 0xD4 },
{ 0xC9, 0x00 },
{ 0xCA, 0x00 },
{ 0xCB, 0x16 },
{ 0xCC, 0xAF },
{ 0xCD, 0xFF },
{ 0xCE, 0xFF },
{ 0xB0, 0x0B },
{ 0xB1, 0x04 },
{ 0xB2, 0x05 },
{ 0xB3, 0x11 },
{ 0xB4, 0x24 },
{ 0xB5, 0x39 },
{ 0xB6, 0x4E },
{ 0xB7, 0x72 },
{ 0xB8, 0xA3 },
{ 0xB9, 0xE1 },
{ 0xBA, 0x25 },
{ 0xBB, 0xA8 },
{ 0xBC, 0x2E },
{ 0xBD, 0x32 },
{ 0xBE, 0xAD },
{ 0xBF, 0x28 },
{ 0xC0, 0x63 },
{ 0xC1, 0x9B },
{ 0xC2, 0xB5 },
{ 0xC3, 0xCF },
{ 0xC4, 0xDB },
{ 0xC5, 0xE8 },
{ 0xC6, 0xF5 },
{ 0xC7, 0xFA },
{ 0xC8, 0xFC },
{ 0xC9, 0x00 },
{ 0xCA, 0x00 },
{ 0xCB, 0x16 },
{ 0xCC, 0xAF },
{ 0xCD, 0xFF },
{ 0xCE, 0xFF },
{ 0xB0, 0x0C },
{ 0xB1, 0x04 },
{ 0xB2, 0x04 },
{ 0xB3, 0x0F },
{ 0xB4, 0x22 },
{ 0xB5, 0x37 },
{ 0xB6, 0x4D },
{ 0xB7, 0x71 },
{ 0xB8, 0xA2 },
{ 0xB9, 0xE1 },
{ 0xBA, 0x26 },
{ 0xBB, 0xA9 },
{ 0xBC, 0x2F },
{ 0xBD, 0x33 },
{ 0xBE, 0xAC },
{ 0xBF, 0x24 },
{ 0xC0, 0x5D },
{ 0xC1, 0x94 },
{ 0xC2, 0xAC },
{ 0xC3, 0xC5 },
{ 0xC4, 0xD1 },
{ 0xC5, 0xDC },
{ 0xC6, 0xE8 },
{ 0xC7, 0xED },
{ 0xC8, 0xF0 },
{ 0xC9, 0x00 },
{ 0xCA, 0x00 },
{ 0xCB, 0x16 },
{ 0xCC, 0xAF },
{ 0xCD, 0xFF },
{ 0xCE, 0xFF },
};
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)) {
ret = PTR_ERR(pinfo->pp18_gpio);
if (ret != -EPROBE_DEFER)
dev_err(dev, "failed to get pp18 gpio: %d\n", ret);
return ret;
}
pinfo->pp33_gpio = devm_gpiod_get(dev, "pp33", GPIOD_OUT_HIGH);
if (IS_ERR(pinfo->pp33_gpio)) {
ret = PTR_ERR(pinfo->pp33_gpio);
if (ret != -EPROBE_DEFER)
dev_err(dev, "failed to get pp33 gpio: %d\n", ret);
return ret;
}
pinfo->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
if (IS_ERR(pinfo->enable_gpio)) {
ret = PTR_ERR(pinfo->enable_gpio);
if (ret != -EPROBE_DEFER)
dev_err(dev, "failed to get enable gpio: %d\n", ret);
return ret;
}
drm_panel_init(&pinfo->base, dev, &panel_funcs,
DRM_MODE_CONNECTOR_DSI);
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_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;
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 = boe_panel_disable(&pinfo->base);
if (err < 0)
dev_err(&dsi->dev, "failed to disable panel: %d\n", err);
err = boe_panel_unprepare(&pinfo->base);
if (err < 0)
dev_err(&dsi->dev, "failed to unprepare panel: %d\n", 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 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");