// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 BayLibre, SAS
* Author: Neil Armstrong <narmstrong@baylibre.com>
*/
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <video/mipi_display.h>
#include <drm/drm_crtc.h>
#include <drm/drm_device.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_modes.h>
#include <drm/drm_panel.h>
struct khadas_ts050_panel {
struct drm_panel base;
struct mipi_dsi_device *link;
struct regulator *supply;
struct gpio_desc *reset_gpio;
struct gpio_desc *enable_gpio;
struct khadas_ts050_panel_data *panel_data;
};
struct khadas_ts050_panel_cmd {
u8 cmd;
u8 data[55 ];
u8 size;
};
struct khadas_ts050_panel_data {
struct khadas_ts050_panel_cmd *init_code;
int len;
};
static const struct khadas_ts050_panel_cmd ts050v2_init_code[] = {
{0 xB9, {0 xFF, 0 x83, 0 x99}, 0 x03},
{0 xBA, {0 x63, 0 x23, 0 x68, 0 xCF}, 0 x04},
{0 xD2, {0 x55}, 0 x01},
{0 xB1, {0 x02, 0 x04, 0 x70, 0 x90, 0 x01, 0 x32, 0 x33,
0 x11, 0 x11, 0 x4D, 0 x57, 0 x56, 0 x73, 0 x02, 0 x02}, 0 x0f},
{0 xB2, {0 x00, 0 x80, 0 x80, 0 xAE, 0 x0A, 0 x0E, 0 x75, 0 x11, 0 x00, 0 x00, 0 x00}, 0 x0b},
{0 xB4, {0 x00, 0 xFF, 0 x04, 0 xA4, 0 x02, 0 xA0, 0 x00, 0 x00, 0 x10, 0 x00, 0 x00, 0 x02,
0 x00, 0 x24, 0 x02, 0 x04, 0 x0A, 0 x21, 0 x03, 0 x00, 0 x00, 0 x08, 0 xA6, 0 x88,
0 x04, 0 xA4, 0 x02, 0 xA0, 0 x00, 0 x00, 0 x10, 0 x00, 0 x00, 0 x02, 0 x00, 0 x24,
0 x02, 0 x04, 0 x0A, 0 x00, 0 x00, 0 x08, 0 xA6, 0 x00, 0 x08, 0 x11}, 0 x2e},
{0 xD3, {0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x18,
0 x18, 0 x32, 0 x10, 0 x09, 0 x00, 0 x09, 0 x32,
0 x10, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x11, 0 x00, 0 x02, 0 x02, 0 x03, 0 x00, 0 x00, 0 x00, 0 x0A,
0 x40}, 0 x21},
{0 xD5, {0 x18, 0 x18, 0 x18, 0 x18, 0 x21, 0 x20, 0 x18, 0 x18, 0 x19, 0 x19, 0 x19,
0 x19, 0 x18, 0 x18, 0 x18, 0 x18, 0 x03, 0 x02, 0 x01, 0 x00, 0 x2F, 0 x2F,
0 x30, 0 x30, 0 x31, 0 x31, 0 x18, 0 x18, 0 x18, 0 x18, 0 x18, 0 x18}, 0 x20},
{0 xD6, {0 x18, 0 x18, 0 x18, 0 x18, 0 x20, 0 x21, 0 x19, 0 x19, 0 x18, 0 x18, 0 x19,
0 x19, 0 x18, 0 x18, 0 x18, 0 x18, 0 x00, 0 x01, 0 x02, 0 x03, 0 x2F, 0 x2F,
0 x30, 0 x30, 0 x31, 0 x31, 0 x18, 0 x18, 0 x18, 0 x18, 0 x18, 0 x18}, 0 x20},
{0 xD8, {0 x0A, 0 xBE, 0 xFA, 0 xA0, 0 x0A, 0 xBE, 0 xFA, 0 xA0}, 0 x08},
{0 xBD, {0 x01}, 0 x01},
{0 xD8, {0 x0F, 0 xFF, 0 xFF, 0 xE0, 0 x0F, 0 xFF, 0 xFF, 0 xE0}, 0 x08},
{0 xBD, {0 x02}, 0 x01},
{0 xD8, {0 x0F, 0 xFF, 0 xFF, 0 xE0, 0 x0F, 0 xFF, 0 xFF, 0 xE0}, 0 x08},
{0 xBD, {0 x00}, 0 x01},
{0 xE0, {0 x01, 0 x35, 0 x41, 0 x3B, 0 x79, 0 x81, 0 x8C, 0 x85, 0 x8E,
0 x95, 0 x9B, 0 xA0, 0 xA4, 0 xAB, 0 xB1, 0 xB3, 0 xB7, 0 xC5, 0 xBD, 0 xC5,
0 xB6, 0 xC2, 0 xC2, 0 x62, 0 x5D, 0 x66, 0 x73, 0 x01, 0 x35, 0 x41, 0 x3B,
0 x79, 0 x81, 0 x8C, 0 x85, 0 x8E, 0 x95, 0 x9B, 0 xA0, 0 xA4, 0 xAB, 0 xB1,
0 xB3, 0 xB7, 0 xB5, 0 xBD, 0 xC5, 0 xB6, 0 xC2, 0 xC2, 0 x62, 0 x5D, 0 x66,
0 x73}, 0 x36},
{0 xB6, {0 x97, 0 x97}, 0 x02},
{0 xCC, {0 xC8}, 0 x02},
{0 xBF, {0 x40, 0 x41, 0 x50, 0 x19}, 0 x04},
{0 xC6, {0 xFF, 0 xF9}, 0 x02},
{0 xC0, {0 x25, 0 x5A}, 0 x02},
};
/* Only the CMD1 User Command set is documented */
static const struct khadas_ts050_panel_cmd ts050_init_code[] = {
/* Select Unknown CMD Page (Undocumented) */
{0 xff, {0 xee}, 0 x01},
/* Reload CMD1: Don't reload default value to register */
{0 xfb, {0 x01}, 0 x01},
{0 x1f, {0 x45}, 0 x01},
{0 x24, {0 x4f}, 0 x01},
{0 x38, {0 xc8}, 0 x01},
{0 x39, {0 x27}, 0 x01},
{0 x1e, {0 x77}, 0 x01},
{0 x1d, {0 x0f}, 0 x01},
{0 x7e, {0 x71}, 0 x01},
{0 x7c, {0 x03}, 0 x01},
{0 xff, {0 x00}, 0 x01},
{0 xfb, {0 x01}, 0 x01},
{0 x35, {0 x01}, 0 x01},
/* Select CMD2 Page0 (Undocumented) */
{0 xff, {0 x01}, 0 x01},
/* Reload CMD1: Don't reload default value to register */
{0 xfb, {0 x01}, 0 x01},
{0 x00, {0 x01}, 0 x01},
{0 x01, {0 x55}, 0 x01},
{0 x02, {0 x40}, 0 x01},
{0 x05, {0 x40}, 0 x01},
{0 x06, {0 x4a}, 0 x01},
{0 x07, {0 x24}, 0 x01},
{0 x08, {0 x0c}, 0 x01},
{0 x0b, {0 x7d}, 0 x01},
{0 x0c, {0 x7d}, 0 x01},
{0 x0e, {0 xb0}, 0 x01},
{0 x0f, {0 xae}, 0 x01},
{0 x11, {0 x10}, 0 x01},
{0 x12, {0 x10}, 0 x01},
{0 x13, {0 x03}, 0 x01},
{0 x14, {0 x4a}, 0 x01},
{0 x15, {0 x12}, 0 x01},
{0 x16, {0 x12}, 0 x01},
{0 x18, {0 x00}, 0 x01},
{0 x19, {0 x77}, 0 x01},
{0 x1a, {0 x55}, 0 x01},
{0 x1b, {0 x13}, 0 x01},
{0 x1c, {0 x00}, 0 x01},
{0 x1d, {0 x00}, 0 x01},
{0 x1e, {0 x13}, 0 x01},
{0 x1f, {0 x00}, 0 x01},
{0 x23, {0 x00}, 0 x01},
{0 x24, {0 x00}, 0 x01},
{0 x25, {0 x00}, 0 x01},
{0 x26, {0 x00}, 0 x01},
{0 x27, {0 x00}, 0 x01},
{0 x28, {0 x00}, 0 x01},
{0 x35, {0 x00}, 0 x01},
{0 x66, {0 x00}, 0 x01},
{0 x58, {0 x82}, 0 x01},
{0 x59, {0 x02}, 0 x01},
{0 x5a, {0 x02}, 0 x01},
{0 x5b, {0 x02}, 0 x01},
{0 x5c, {0 x82}, 0 x01},
{0 x5d, {0 x82}, 0 x01},
{0 x5e, {0 x02}, 0 x01},
{0 x5f, {0 x02}, 0 x01},
{0 x72, {0 x31}, 0 x01},
/* Select CMD2 Page4 (Undocumented) */
{0 xff, {0 x05}, 0 x01},
/* Reload CMD1: Don't reload default value to register */
{0 xfb, {0 x01}, 0 x01},
{0 x00, {0 x01}, 0 x01},
{0 x01, {0 x0b}, 0 x01},
{0 x02, {0 x0c}, 0 x01},
{0 x03, {0 x09}, 0 x01},
{0 x04, {0 x0a}, 0 x01},
{0 x05, {0 x00}, 0 x01},
{0 x06, {0 x0f}, 0 x01},
{0 x07, {0 x10}, 0 x01},
{0 x08, {0 x00}, 0 x01},
{0 x09, {0 x00}, 0 x01},
{0 x0a, {0 x00}, 0 x01},
{0 x0b, {0 x00}, 0 x01},
{0 x0c, {0 x00}, 0 x01},
{0 x0d, {0 x13}, 0 x01},
{0 x0e, {0 x15}, 0 x01},
{0 x0f, {0 x17}, 0 x01},
{0 x10, {0 x01}, 0 x01},
{0 x11, {0 x0b}, 0 x01},
{0 x12, {0 x0c}, 0 x01},
{0 x13, {0 x09}, 0 x01},
{0 x14, {0 x0a}, 0 x01},
{0 x15, {0 x00}, 0 x01},
{0 x16, {0 x0f}, 0 x01},
{0 x17, {0 x10}, 0 x01},
{0 x18, {0 x00}, 0 x01},
{0 x19, {0 x00}, 0 x01},
{0 x1a, {0 x00}, 0 x01},
{0 x1b, {0 x00}, 0 x01},
{0 x1c, {0 x00}, 0 x01},
{0 x1d, {0 x13}, 0 x01},
{0 x1e, {0 x15}, 0 x01},
{0 x1f, {0 x17}, 0 x01},
{0 x20, {0 x00}, 0 x01},
{0 x21, {0 x03}, 0 x01},
{0 x22, {0 x01}, 0 x01},
{0 x23, {0 x40}, 0 x01},
{0 x24, {0 x40}, 0 x01},
{0 x25, {0 xed}, 0 x01},
{0 x29, {0 x58}, 0 x01},
{0 x2a, {0 x12}, 0 x01},
{0 x2b, {0 x01}, 0 x01},
{0 x4b, {0 x06}, 0 x01},
{0 x4c, {0 x11}, 0 x01},
{0 x4d, {0 x20}, 0 x01},
{0 x4e, {0 x02}, 0 x01},
{0 x4f, {0 x02}, 0 x01},
{0 x50, {0 x20}, 0 x01},
{0 x51, {0 x61}, 0 x01},
{0 x52, {0 x01}, 0 x01},
{0 x53, {0 x63}, 0 x01},
{0 x54, {0 x77}, 0 x01},
{0 x55, {0 xed}, 0 x01},
{0 x5b, {0 x00}, 0 x01},
{0 x5c, {0 x00}, 0 x01},
{0 x5d, {0 x00}, 0 x01},
{0 x5e, {0 x00}, 0 x01},
{0 x5f, {0 x15}, 0 x01},
{0 x60, {0 x75}, 0 x01},
{0 x61, {0 x00}, 0 x01},
{0 x62, {0 x00}, 0 x01},
{0 x63, {0 x00}, 0 x01},
{0 x64, {0 x00}, 0 x01},
{0 x65, {0 x00}, 0 x01},
{0 x66, {0 x00}, 0 x01},
{0 x67, {0 x00}, 0 x01},
{0 x68, {0 x04}, 0 x01},
{0 x69, {0 x00}, 0 x01},
{0 x6a, {0 x00}, 0 x01},
{0 x6c, {0 x40}, 0 x01},
{0 x75, {0 x01}, 0 x01},
{0 x76, {0 x01}, 0 x01},
{0 x7a, {0 x80}, 0 x01},
{0 x7b, {0 xa3}, 0 x01},
{0 x7c, {0 xd8}, 0 x01},
{0 x7d, {0 x60}, 0 x01},
{0 x7f, {0 x15}, 0 x01},
{0 x80, {0 x81}, 0 x01},
{0 x83, {0 x05}, 0 x01},
{0 x93, {0 x08}, 0 x01},
{0 x94, {0 x10}, 0 x01},
{0 x8a, {0 x00}, 0 x01},
{0 x9b, {0 x0f}, 0 x01},
{0 xea, {0 xff}, 0 x01},
{0 xec, {0 x00}, 0 x01},
/* Select CMD2 Page0 (Undocumented) */
{0 xff, {0 x01}, 0 x01},
/* Reload CMD1: Don't reload default value to register */
{0 xfb, {0 x01}, 0 x01},
{0 x75, {0 x00}, 0 x01},
{0 x76, {0 xdf}, 0 x01},
{0 x77, {0 x00}, 0 x01},
{0 x78, {0 xe4}, 0 x01},
{0 x79, {0 x00}, 0 x01},
{0 x7a, {0 xed}, 0 x01},
{0 x7b, {0 x00}, 0 x01},
{0 x7c, {0 xf6}, 0 x01},
{0 x7d, {0 x00}, 0 x01},
{0 x7e, {0 xff}, 0 x01},
{0 x7f, {0 x01}, 0 x01},
{0 x80, {0 x07}, 0 x01},
{0 x81, {0 x01}, 0 x01},
{0 x82, {0 x10}, 0 x01},
{0 x83, {0 x01}, 0 x01},
{0 x84, {0 x18}, 0 x01},
{0 x85, {0 x01}, 0 x01},
{0 x86, {0 x20}, 0 x01},
{0 x87, {0 x01}, 0 x01},
{0 x88, {0 x3d}, 0 x01},
{0 x89, {0 x01}, 0 x01},
{0 x8a, {0 x56}, 0 x01},
{0 x8b, {0 x01}, 0 x01},
{0 x8c, {0 x84}, 0 x01},
{0 x8d, {0 x01}, 0 x01},
{0 x8e, {0 xab}, 0 x01},
{0 x8f, {0 x01}, 0 x01},
{0 x90, {0 xec}, 0 x01},
{0 x91, {0 x02}, 0 x01},
{0 x92, {0 x22}, 0 x01},
{0 x93, {0 x02}, 0 x01},
{0 x94, {0 x23}, 0 x01},
{0 x95, {0 x02}, 0 x01},
{0 x96, {0 x55}, 0 x01},
{0 x97, {0 x02}, 0 x01},
{0 x98, {0 x8b}, 0 x01},
{0 x99, {0 x02}, 0 x01},
{0 x9a, {0 xaf}, 0 x01},
{0 x9b, {0 x02}, 0 x01},
{0 x9c, {0 xdf}, 0 x01},
{0 x9d, {0 x03}, 0 x01},
{0 x9e, {0 x01}, 0 x01},
{0 x9f, {0 x03}, 0 x01},
{0 xa0, {0 x2c}, 0 x01},
{0 xa2, {0 x03}, 0 x01},
{0 xa3, {0 x39}, 0 x01},
{0 xa4, {0 x03}, 0 x01},
{0 xa5, {0 x47}, 0 x01},
{0 xa6, {0 x03}, 0 x01},
{0 xa7, {0 x56}, 0 x01},
{0 xa9, {0 x03}, 0 x01},
{0 xaa, {0 x66}, 0 x01},
{0 xab, {0 x03}, 0 x01},
{0 xac, {0 x76}, 0 x01},
{0 xad, {0 x03}, 0 x01},
{0 xae, {0 x85}, 0 x01},
{0 xaf, {0 x03}, 0 x01},
{0 xb0, {0 x90}, 0 x01},
{0 xb1, {0 x03}, 0 x01},
{0 xb2, {0 xcb}, 0 x01},
{0 xb3, {0 x00}, 0 x01},
{0 xb4, {0 xdf}, 0 x01},
{0 xb5, {0 x00}, 0 x01},
{0 xb6, {0 xe4}, 0 x01},
{0 xb7, {0 x00}, 0 x01},
{0 xb8, {0 xed}, 0 x01},
{0 xb9, {0 x00}, 0 x01},
{0 xba, {0 xf6}, 0 x01},
{0 xbb, {0 x00}, 0 x01},
{0 xbc, {0 xff}, 0 x01},
{0 xbd, {0 x01}, 0 x01},
{0 xbe, {0 x07}, 0 x01},
{0 xbf, {0 x01}, 0 x01},
{0 xc0, {0 x10}, 0 x01},
{0 xc1, {0 x01}, 0 x01},
{0 xc2, {0 x18}, 0 x01},
{0 xc3, {0 x01}, 0 x01},
{0 xc4, {0 x20}, 0 x01},
{0 xc5, {0 x01}, 0 x01},
{0 xc6, {0 x3d}, 0 x01},
{0 xc7, {0 x01}, 0 x01},
{0 xc8, {0 x56}, 0 x01},
{0 xc9, {0 x01}, 0 x01},
{0 xca, {0 x84}, 0 x01},
{0 xcb, {0 x01}, 0 x01},
{0 xcc, {0 xab}, 0 x01},
{0 xcd, {0 x01}, 0 x01},
{0 xce, {0 xec}, 0 x01},
{0 xcf, {0 x02}, 0 x01},
{0 xd0, {0 x22}, 0 x01},
{0 xd1, {0 x02}, 0 x01},
{0 xd2, {0 x23}, 0 x01},
{0 xd3, {0 x02}, 0 x01},
{0 xd4, {0 x55}, 0 x01},
{0 xd5, {0 x02}, 0 x01},
{0 xd6, {0 x8b}, 0 x01},
{0 xd7, {0 x02}, 0 x01},
{0 xd8, {0 xaf}, 0 x01},
{0 xd9, {0 x02}, 0 x01},
{0 xda, {0 xdf}, 0 x01},
{0 xdb, {0 x03}, 0 x01},
{0 xdc, {0 x01}, 0 x01},
{0 xdd, {0 x03}, 0 x01},
{0 xde, {0 x2c}, 0 x01},
{0 xdf, {0 x03}, 0 x01},
{0 xe0, {0 x39}, 0 x01},
{0 xe1, {0 x03}, 0 x01},
{0 xe2, {0 x47}, 0 x01},
{0 xe3, {0 x03}, 0 x01},
{0 xe4, {0 x56}, 0 x01},
{0 xe5, {0 x03}, 0 x01},
{0 xe6, {0 x66}, 0 x01},
{0 xe7, {0 x03}, 0 x01},
{0 xe8, {0 x76}, 0 x01},
{0 xe9, {0 x03}, 0 x01},
{0 xea, {0 x85}, 0 x01},
{0 xeb, {0 x03}, 0 x01},
{0 xec, {0 x90}, 0 x01},
{0 xed, {0 x03}, 0 x01},
{0 xee, {0 xcb}, 0 x01},
{0 xef, {0 x00}, 0 x01},
{0 xf0, {0 xbb}, 0 x01},
{0 xf1, {0 x00}, 0 x01},
{0 xf2, {0 xc0}, 0 x01},
{0 xf3, {0 x00}, 0 x01},
{0 xf4, {0 xcc}, 0 x01},
{0 xf5, {0 x00}, 0 x01},
{0 xf6, {0 xd6}, 0 x01},
{0 xf7, {0 x00}, 0 x01},
{0 xf8, {0 xe1}, 0 x01},
{0 xf9, {0 x00}, 0 x01},
{0 xfa, {0 xea}, 0 x01},
/* Select CMD2 Page2 (Undocumented) */
{0 xff, {0 x02}, 0 x01},
/* Reload CMD1: Don't reload default value to register */
{0 xfb, {0 x01}, 0 x01},
{0 x00, {0 x00}, 0 x01},
{0 x01, {0 xf4}, 0 x01},
{0 x02, {0 x00}, 0 x01},
{0 x03, {0 xef}, 0 x01},
{0 x04, {0 x01}, 0 x01},
{0 x05, {0 x07}, 0 x01},
{0 x06, {0 x01}, 0 x01},
{0 x07, {0 x28}, 0 x01},
{0 x08, {0 x01}, 0 x01},
{0 x09, {0 x44}, 0 x01},
{0 x0a, {0 x01}, 0 x01},
{0 x0b, {0 x76}, 0 x01},
{0 x0c, {0 x01}, 0 x01},
{0 x0d, {0 xa0}, 0 x01},
{0 x0e, {0 x01}, 0 x01},
{0 x0f, {0 xe7}, 0 x01},
{0 x10, {0 x02}, 0 x01},
{0 x11, {0 x1f}, 0 x01},
{0 x12, {0 x02}, 0 x01},
{0 x13, {0 x22}, 0 x01},
{0 x14, {0 x02}, 0 x01},
{0 x15, {0 x54}, 0 x01},
{0 x16, {0 x02}, 0 x01},
{0 x17, {0 x8b}, 0 x01},
{0 x18, {0 x02}, 0 x01},
{0 x19, {0 xaf}, 0 x01},
{0 x1a, {0 x02}, 0 x01},
{0 x1b, {0 xe0}, 0 x01},
{0 x1c, {0 x03}, 0 x01},
{0 x1d, {0 x01}, 0 x01},
{0 x1e, {0 x03}, 0 x01},
{0 x1f, {0 x2d}, 0 x01},
{0 x20, {0 x03}, 0 x01},
{0 x21, {0 x39}, 0 x01},
{0 x22, {0 x03}, 0 x01},
{0 x23, {0 x47}, 0 x01},
{0 x24, {0 x03}, 0 x01},
{0 x25, {0 x57}, 0 x01},
{0 x26, {0 x03}, 0 x01},
{0 x27, {0 x65}, 0 x01},
{0 x28, {0 x03}, 0 x01},
{0 x29, {0 x77}, 0 x01},
{0 x2a, {0 x03}, 0 x01},
{0 x2b, {0 x85}, 0 x01},
{0 x2d, {0 x03}, 0 x01},
{0 x2f, {0 x8f}, 0 x01},
{0 x30, {0 x03}, 0 x01},
{0 x31, {0 xcb}, 0 x01},
{0 x32, {0 x00}, 0 x01},
{0 x33, {0 xbb}, 0 x01},
{0 x34, {0 x00}, 0 x01},
{0 x35, {0 xc0}, 0 x01},
{0 x36, {0 x00}, 0 x01},
{0 x37, {0 xcc}, 0 x01},
{0 x38, {0 x00}, 0 x01},
{0 x39, {0 xd6}, 0 x01},
{0 x3a, {0 x00}, 0 x01},
{0 x3b, {0 xe1}, 0 x01},
{0 x3d, {0 x00}, 0 x01},
{0 x3f, {0 xea}, 0 x01},
{0 x40, {0 x00}, 0 x01},
{0 x41, {0 xf4}, 0 x01},
{0 x42, {0 x00}, 0 x01},
{0 x43, {0 xfe}, 0 x01},
{0 x44, {0 x01}, 0 x01},
{0 x45, {0 x07}, 0 x01},
{0 x46, {0 x01}, 0 x01},
{0 x47, {0 x28}, 0 x01},
{0 x48, {0 x01}, 0 x01},
{0 x49, {0 x44}, 0 x01},
{0 x4a, {0 x01}, 0 x01},
{0 x4b, {0 x76}, 0 x01},
{0 x4c, {0 x01}, 0 x01},
{0 x4d, {0 xa0}, 0 x01},
{0 x4e, {0 x01}, 0 x01},
{0 x4f, {0 xe7}, 0 x01},
{0 x50, {0 x02}, 0 x01},
{0 x51, {0 x1f}, 0 x01},
{0 x52, {0 x02}, 0 x01},
{0 x53, {0 x22}, 0 x01},
{0 x54, {0 x02}, 0 x01},
{0 x55, {0 x54}, 0 x01},
{0 x56, {0 x02}, 0 x01},
{0 x58, {0 x8b}, 0 x01},
{0 x59, {0 x02}, 0 x01},
{0 x5a, {0 xaf}, 0 x01},
{0 x5b, {0 x02}, 0 x01},
{0 x5c, {0 xe0}, 0 x01},
{0 x5d, {0 x03}, 0 x01},
{0 x5e, {0 x01}, 0 x01},
{0 x5f, {0 x03}, 0 x01},
{0 x60, {0 x2d}, 0 x01},
{0 x61, {0 x03}, 0 x01},
{0 x62, {0 x39}, 0 x01},
{0 x63, {0 x03}, 0 x01},
{0 x64, {0 x47}, 0 x01},
{0 x65, {0 x03}, 0 x01},
{0 x66, {0 x57}, 0 x01},
{0 x67, {0 x03}, 0 x01},
{0 x68, {0 x65}, 0 x01},
{0 x69, {0 x03}, 0 x01},
{0 x6a, {0 x77}, 0 x01},
{0 x6b, {0 x03}, 0 x01},
{0 x6c, {0 x85}, 0 x01},
{0 x6d, {0 x03}, 0 x01},
{0 x6e, {0 x8f}, 0 x01},
{0 x6f, {0 x03}, 0 x01},
{0 x70, {0 xcb}, 0 x01},
{0 x71, {0 x00}, 0 x01},
{0 x72, {0 x00}, 0 x01},
{0 x73, {0 x00}, 0 x01},
{0 x74, {0 x21}, 0 x01},
{0 x75, {0 x00}, 0 x01},
{0 x76, {0 x4c}, 0 x01},
{0 x77, {0 x00}, 0 x01},
{0 x78, {0 x6b}, 0 x01},
{0 x79, {0 x00}, 0 x01},
{0 x7a, {0 x85}, 0 x01},
{0 x7b, {0 x00}, 0 x01},
{0 x7c, {0 x9a}, 0 x01},
{0 x7d, {0 x00}, 0 x01},
{0 x7e, {0 xad}, 0 x01},
{0 x7f, {0 x00}, 0 x01},
{0 x80, {0 xbe}, 0 x01},
{0 x81, {0 x00}, 0 x01},
{0 x82, {0 xcd}, 0 x01},
{0 x83, {0 x01}, 0 x01},
{0 x84, {0 x01}, 0 x01},
{0 x85, {0 x01}, 0 x01},
{0 x86, {0 x29}, 0 x01},
{0 x87, {0 x01}, 0 x01},
{0 x88, {0 x68}, 0 x01},
{0 x89, {0 x01}, 0 x01},
{0 x8a, {0 x98}, 0 x01},
{0 x8b, {0 x01}, 0 x01},
{0 x8c, {0 xe5}, 0 x01},
{0 x8d, {0 x02}, 0 x01},
{0 x8e, {0 x1e}, 0 x01},
{0 x8f, {0 x02}, 0 x01},
{0 x90, {0 x30}, 0 x01},
{0 x91, {0 x02}, 0 x01},
{0 x92, {0 x52}, 0 x01},
{0 x93, {0 x02}, 0 x01},
{0 x94, {0 x88}, 0 x01},
{0 x95, {0 x02}, 0 x01},
{0 x96, {0 xaa}, 0 x01},
{0 x97, {0 x02}, 0 x01},
{0 x98, {0 xd7}, 0 x01},
{0 x99, {0 x02}, 0 x01},
{0 x9a, {0 xf7}, 0 x01},
{0 x9b, {0 x03}, 0 x01},
{0 x9c, {0 x21}, 0 x01},
{0 x9d, {0 x03}, 0 x01},
{0 x9e, {0 x2e}, 0 x01},
{0 x9f, {0 x03}, 0 x01},
{0 xa0, {0 x3d}, 0 x01},
{0 xa2, {0 x03}, 0 x01},
{0 xa3, {0 x4c}, 0 x01},
{0 xa4, {0 x03}, 0 x01},
{0 xa5, {0 x5e}, 0 x01},
{0 xa6, {0 x03}, 0 x01},
{0 xa7, {0 x71}, 0 x01},
{0 xa9, {0 x03}, 0 x01},
{0 xaa, {0 x86}, 0 x01},
{0 xab, {0 x03}, 0 x01},
{0 xac, {0 x94}, 0 x01},
{0 xad, {0 x03}, 0 x01},
{0 xae, {0 xfa}, 0 x01},
{0 xaf, {0 x00}, 0 x01},
{0 xb0, {0 x00}, 0 x01},
{0 xb1, {0 x00}, 0 x01},
{0 xb2, {0 x21}, 0 x01},
{0 xb3, {0 x00}, 0 x01},
{0 xb4, {0 x4c}, 0 x01},
{0 xb5, {0 x00}, 0 x01},
{0 xb6, {0 x6b}, 0 x01},
{0 xb7, {0 x00}, 0 x01},
{0 xb8, {0 x85}, 0 x01},
{0 xb9, {0 x00}, 0 x01},
{0 xba, {0 x9a}, 0 x01},
{0 xbb, {0 x00}, 0 x01},
{0 xbc, {0 xad}, 0 x01},
{0 xbd, {0 x00}, 0 x01},
{0 xbe, {0 xbe}, 0 x01},
{0 xbf, {0 x00}, 0 x01},
{0 xc0, {0 xcd}, 0 x01},
{0 xc1, {0 x01}, 0 x01},
{0 xc2, {0 x01}, 0 x01},
{0 xc3, {0 x01}, 0 x01},
{0 xc4, {0 x29}, 0 x01},
{0 xc5, {0 x01}, 0 x01},
{0 xc6, {0 x68}, 0 x01},
{0 xc7, {0 x01}, 0 x01},
{0 xc8, {0 x98}, 0 x01},
{0 xc9, {0 x01}, 0 x01},
{0 xca, {0 xe5}, 0 x01},
{0 xcb, {0 x02}, 0 x01},
{0 xcc, {0 x1e}, 0 x01},
{0 xcd, {0 x02}, 0 x01},
{0 xce, {0 x20}, 0 x01},
{0 xcf, {0 x02}, 0 x01},
{0 xd0, {0 x52}, 0 x01},
{0 xd1, {0 x02}, 0 x01},
{0 xd2, {0 x88}, 0 x01},
{0 xd3, {0 x02}, 0 x01},
{0 xd4, {0 xaa}, 0 x01},
{0 xd5, {0 x02}, 0 x01},
{0 xd6, {0 xd7}, 0 x01},
{0 xd7, {0 x02}, 0 x01},
{0 xd8, {0 xf7}, 0 x01},
{0 xd9, {0 x03}, 0 x01},
{0 xda, {0 x21}, 0 x01},
{0 xdb, {0 x03}, 0 x01},
{0 xdc, {0 x2e}, 0 x01},
{0 xdd, {0 x03}, 0 x01},
{0 xde, {0 x3d}, 0 x01},
{0 xdf, {0 x03}, 0 x01},
{0 xe0, {0 x4c}, 0 x01},
{0 xe1, {0 x03}, 0 x01},
{0 xe2, {0 x5e}, 0 x01},
{0 xe3, {0 x03}, 0 x01},
{0 xe4, {0 x71}, 0 x01},
{0 xe5, {0 x03}, 0 x01},
{0 xe6, {0 x86}, 0 x01},
{0 xe7, {0 x03}, 0 x01},
{0 xe8, {0 x94}, 0 x01},
{0 xe9, {0 x03}, 0 x01},
{0 xea, {0 xfa}, 0 x01},
/* Select CMD2 Page0 (Undocumented) */
{0 xff, {0 x01}, 0 x01},
/* Reload CMD1: Don't reload default value to register */
{0 xfb, {0 x01}, 0 x01},
/* Select CMD2 Page1 (Undocumented) */
{0 xff, {0 x02}, 0 x01},
/* Reload CMD1: Don't reload default value to register */
{0 xfb, {0 x01}, 0 x01},
/* Select CMD2 Page3 (Undocumented) */
{0 xff, {0 x04}, 0 x01},
/* Reload CMD1: Don't reload default value to register */
{0 xfb, {0 x01}, 0 x01},
/* Select CMD1 */
{0 xff, {0 x00}, 0 x01},
{0 xd3, {0 x22}, 0 x01}, /* RGBMIPICTRL: VSYNC back porch = 34 */
{0 xd4, {0 x04}, 0 x01}, /* RGBMIPICTRL: VSYNC front porch = 4 */
};
static struct khadas_ts050_panel_data ts050_panel_data = {
.init_code = (struct khadas_ts050_panel_cmd *)ts050_init_code,
.len = ARRAY_SIZE(ts050_init_code)
};
static struct khadas_ts050_panel_data ts050v2_panel_data = {
.init_code = (struct khadas_ts050_panel_cmd *)ts050v2_init_code,
.len = ARRAY_SIZE(ts050v2_init_code)
};
static inline
struct khadas_ts050_panel *to_khadas_ts050_panel(struct drm_panel *panel)
{
return container_of(panel, struct khadas_ts050_panel, base);
}
static int khadas_ts050_panel_prepare(struct drm_panel *panel)
{
struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel);
unsigned int i;
int err;
gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 0 );
err = regulator_enable(khadas_ts050->supply);
if (err < 0 )
return err;
gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 1 );
msleep(60 );
gpiod_set_value_cansleep(khadas_ts050->reset_gpio, 1 );
usleep_range(10000 , 11000 );
gpiod_set_value_cansleep(khadas_ts050->reset_gpio, 0 );
/* Select CMD2 page 4 (Undocumented) */
mipi_dsi_dcs_write(khadas_ts050->link, 0 xff, (u8[]){ 0 x05 }, 1 );
/* Reload CMD1: Don't reload default value to register */
mipi_dsi_dcs_write(khadas_ts050->link, 0 xfb, (u8[]){ 0 x01 }, 1 );
mipi_dsi_dcs_write(khadas_ts050->link, 0 xc5, (u8[]){ 0 x01 }, 1 );
msleep(100 );
for (i = 0 ; i < khadas_ts050->panel_data->len; i++) {
err = mipi_dsi_dcs_write(khadas_ts050->link,
khadas_ts050->panel_data->init_code[i].cmd,
&khadas_ts050->panel_data->init_code[i].data,
khadas_ts050->panel_data->init_code[i].size);
if (err < 0 ) {
dev_err(panel->dev, "failed write cmds: %d\n" , err);
goto poweroff;
}
}
err = mipi_dsi_dcs_exit_sleep_mode(khadas_ts050->link);
if (err < 0 ) {
dev_err(panel->dev, "failed to exit sleep mode: %d\n" , err);
goto poweroff;
}
msleep(120 );
/* Select CMD1 */
mipi_dsi_dcs_write(khadas_ts050->link, 0 xff, (u8[]){ 0 x00 }, 1 );
err = mipi_dsi_dcs_set_tear_on(khadas_ts050->link,
MIPI_DSI_DCS_TEAR_MODE_VBLANK);
if (err < 0 ) {
dev_err(panel->dev, "failed to set tear on: %d\n" , err);
goto poweroff;
}
err = mipi_dsi_dcs_set_display_on(khadas_ts050->link);
if (err < 0 ) {
dev_err(panel->dev, "failed to set display on: %d\n" , err);
goto poweroff;
}
usleep_range(10000 , 11000 );
return 0 ;
poweroff:
gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 0 );
gpiod_set_value_cansleep(khadas_ts050->reset_gpio, 1 );
regulator_disable(khadas_ts050->supply);
return err;
}
static int khadas_ts050_panel_unprepare(struct drm_panel *panel)
{
struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel);
int err;
err = mipi_dsi_dcs_enter_sleep_mode(khadas_ts050->link);
if (err < 0 )
dev_err(panel->dev, "failed to enter sleep mode: %d\n" , err);
msleep(150 );
gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 0 );
gpiod_set_value_cansleep(khadas_ts050->reset_gpio, 1 );
err = regulator_disable(khadas_ts050->supply);
if (err < 0 )
return err;
return 0 ;
}
static int khadas_ts050_panel_disable(struct drm_panel *panel)
{
struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel);
int err;
err = mipi_dsi_dcs_set_display_off(khadas_ts050->link);
if (err < 0 )
dev_err(panel->dev, "failed to set display off: %d\n" , err);
usleep_range(10000 , 11000 );
return 0 ;
}
static const struct drm_display_mode default_mode = {
.clock = 160000 ,
.hdisplay = 1080 ,
.hsync_start = 1080 + 117 ,
.hsync_end = 1080 + 117 + 5 ,
.htotal = 1080 + 117 + 5 + 160 ,
.vdisplay = 1920 ,
.vsync_start = 1920 + 4 ,
.vsync_end = 1920 + 4 + 3 ,
.vtotal = 1920 + 4 + 3 + 31 ,
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
};
static int khadas_ts050_panel_get_modes(struct drm_panel *panel,
struct drm_connector *connector)
{
struct drm_display_mode *mode;
mode = drm_mode_duplicate(connector->dev, &default_mode);
if (!mode) {
dev_err(panel->dev, "failed to add mode %ux%u@%u\n" ,
default_mode.hdisplay, default_mode.vdisplay,
drm_mode_vrefresh(&default_mode));
return -ENOMEM;
}
drm_mode_set_name(mode);
drm_mode_probed_add(connector, mode);
connector->display_info.width_mm = 64 ;
connector->display_info.height_mm = 118 ;
connector->display_info.bpc = 8 ;
return 1 ;
}
static const struct drm_panel_funcs khadas_ts050_panel_funcs = {
.prepare = khadas_ts050_panel_prepare,
.unprepare = khadas_ts050_panel_unprepare,
.disable = khadas_ts050_panel_disable,
.get_modes = khadas_ts050_panel_get_modes,
};
static const struct of_device_id khadas_ts050_of_match[] = {
{ .compatible = "khadas,ts050" , .data = &ts050_panel_data, },
{ .compatible = "khadas,ts050v2" , .data = &ts050v2_panel_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, khadas_ts050_of_match);
static int khadas_ts050_panel_add(struct khadas_ts050_panel *khadas_ts050)
{
struct device *dev = &khadas_ts050->link->dev;
int err;
khadas_ts050->supply = devm_regulator_get(dev, "power" );
if (IS_ERR(khadas_ts050->supply))
return dev_err_probe(dev, PTR_ERR(khadas_ts050->supply),
"failed to get power supply" );
khadas_ts050->reset_gpio = devm_gpiod_get(dev, "reset" ,
GPIOD_OUT_LOW);
if (IS_ERR(khadas_ts050->reset_gpio))
return dev_err_probe(dev, PTR_ERR(khadas_ts050->reset_gpio),
"failed to get reset gpio" );
khadas_ts050->enable_gpio = devm_gpiod_get(dev, "enable" ,
GPIOD_OUT_HIGH);
if (IS_ERR(khadas_ts050->enable_gpio))
return dev_err_probe(dev, PTR_ERR(khadas_ts050->enable_gpio),
"failed to get enable gpio" );
err = drm_panel_of_backlight(&khadas_ts050->base);
if (err)
return err;
drm_panel_add(&khadas_ts050->base);
return 0 ;
}
static int khadas_ts050_panel_probe(struct mipi_dsi_device *dsi)
{
struct khadas_ts050_panel *khadas_ts050;
int err;
const void *data = of_device_get_match_data(&dsi->dev);
if (!data) {
dev_err(&dsi->dev, "No matching data\n" );
return -ENODEV;
}
dsi->lanes = 4 ;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET;
khadas_ts050 = devm_drm_panel_alloc(&dsi->dev, __typeof(*khadas_ts050),
base, &khadas_ts050_panel_funcs,
DRM_MODE_CONNECTOR_DSI);
if (IS_ERR(khadas_ts050))
return PTR_ERR(khadas_ts050);
khadas_ts050->panel_data = (struct khadas_ts050_panel_data *)data;
mipi_dsi_set_drvdata(dsi, khadas_ts050);
khadas_ts050->link = dsi;
err = khadas_ts050_panel_add(khadas_ts050);
if (err < 0 )
return err;
err = mipi_dsi_attach(dsi);
if (err)
drm_panel_remove(&khadas_ts050->base);
return err;
}
static void khadas_ts050_panel_remove(struct mipi_dsi_device *dsi)
{
struct khadas_ts050_panel *khadas_ts050 = 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(&khadas_ts050->base);
}
static struct mipi_dsi_driver khadas_ts050_panel_driver = {
.driver = {
.name = "panel-khadas-ts050" ,
.of_match_table = khadas_ts050_of_match,
},
.probe = khadas_ts050_panel_probe,
.remove = khadas_ts050_panel_remove,
};
module_mipi_dsi_driver(khadas_ts050_panel_driver);
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>" );
MODULE_DESCRIPTION("Khadas TS050 panel driver" );
MODULE_LICENSE("GPL v2" );
Messung V0.5 in Prozent C=86 H=91 G=88