// SPDX-License-Identifier: GPL-2.0-only
/*
* Novatek NT36523 DriverIC panels driver
*
* Copyright (c) 2022, 2023 Jianhua Lu <lujianhua000@gmail.com>
*/
#include <linux/backlight.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/regulator/consumer.h>
#include <video/mipi_display.h>
#include <drm/drm_connector.h>
#include <drm/drm_crtc.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_modes.h>
#include <drm/drm_panel.h>
#define DSI_NUM_MIN 1
#define mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, cmd, seq...) \
do { \
mipi_dsi_dcs_write_seq(dsi0, cmd, seq); \
mipi_dsi_dcs_write_seq(dsi1, cmd, seq); \
} while (0)
struct panel_info {
struct drm_panel panel;
struct mipi_dsi_device *dsi[2];
const struct panel_desc *desc;
enum drm_panel_orientation orientation;
struct gpio_desc *reset_gpio;
struct backlight_device *backlight;
struct regulator *vddio;
};
struct panel_desc {
unsigned int width_mm;
unsigned int height_mm;
unsigned int bpc;
unsigned int lanes;
unsigned long mode_flags;
enum mipi_dsi_pixel_format format;
const struct drm_display_mode *modes;
unsigned int num_modes;
const struct mipi_dsi_device_info dsi_info;
int (*init_sequence)(struct panel_info *pinfo);
bool is_dual_dsi;
bool has_dcs_backlight;
};
static inline struct panel_info *to_panel_info(struct drm_panel *panel)
{
return container_of(panel, struct panel_info, panel);
}
static int elish_boe_init_sequence(struct panel_info *pinfo)
{
struct mipi_dsi_device *dsi0 = pinfo->dsi[0];
struct mipi_dsi_device *dsi1 = pinfo->dsi[1];
/* No datasheet, so write magic init sequence directly */
mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x10);
mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01);
mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xb9, 0x05);
mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x20);
mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01);
mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x18, 0x40);
mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x10);
mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01);
mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xb9, 0x02);
mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xff, 0x23);
mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0xfb, 0x01);
mipi_dsi_dual_dcs_write_seq(dsi0, dsi1, 0x00, 0x80);
mipi_dsi_dual_dcs_write_seq