Skip to content

Commit b0b7c1f

Browse files
Akkiesoftpelwell
authored andcommitted
drm/panel: st7701: Add support for Pimoroni HyperPixel 2.1 Round
HyperPixel2R is another DPI fed/SPI configured panel using ST7701. Add the relevant configuration information to the driver. Signed-off-by: Akira Ouchi <akkiesoft@marokun.net> Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
1 parent 30c02d6 commit b0b7c1f

File tree

1 file changed

+248
-1
lines changed

1 file changed

+248
-1
lines changed

drivers/gpu/drm/panel/panel-sitronix-st7701.c

Lines changed: 248 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/bitfield.h>
1313
#include <linux/gpio/consumer.h>
1414
#include <linux/delay.h>
15+
#include <linux/media-bus-format.h>
1516
#include <linux/module.h>
1617
#include <linux/of.h>
1718
#include <linux/regulator/consumer.h>
@@ -106,6 +107,7 @@ struct st7701_panel_desc {
106107
const struct drm_display_mode *mode;
107108
unsigned int lanes;
108109
enum mipi_dsi_pixel_format format;
110+
u32 mediabus_format;
109111
unsigned int panel_sleep_delay;
110112

111113
/* TFT matrix driver configuration, panel specific. */
@@ -520,6 +522,94 @@ static void rg28xx_gip_sequence(struct st7701 *st7701)
520522
st7701_switch_cmd_bkx(st7701, false, 0);
521523
}
522524

525+
static void txw210001b0_gip_sequence(struct st7701 *st7701)
526+
{
527+
ST7701_WRITE(st7701, MIPI_DCS_SOFT_RESET);
528+
529+
usleep_range(5000, 7000);
530+
531+
st7701_switch_cmd_bkx(st7701, true, 0);
532+
533+
ST7701_WRITE(st7701, ST7701_CMD2_BK0_LNESET, 0x3B, 0x0);
534+
535+
ST7701_WRITE(st7701, ST7701_CMD2_BK0_PORCTRL, 0xB, 0x2);
536+
537+
ST7701_WRITE(st7701, ST7701_CMD2_BK0_INVSEL, 0x0, 0x2);
538+
539+
ST7701_WRITE(st7701, 0xCC, 0x10);
540+
541+
st7701_switch_cmd_bkx(st7701, true, 1);
542+
543+
ST7701_WRITE(st7701, ST7701_CMD2_BK1_VRHS, 0x5D);
544+
545+
ST7701_WRITE(st7701, ST7701_CMD2_BK1_VCOM, 0x43);
546+
547+
ST7701_WRITE(st7701, ST7701_CMD2_BK1_VGHSS, 0x81);
548+
549+
ST7701_WRITE(st7701, ST7701_CMD2_BK1_TESTCMD, 0x80);
550+
551+
ST7701_WRITE(st7701, ST7701_CMD2_BK1_VGLS, 0x43);
552+
553+
ST7701_WRITE(st7701, ST7701_CMD2_BK1_PWCTLR1, 0x85);
554+
555+
ST7701_WRITE(st7701, ST7701_CMD2_BK1_PWCTLR2, 0x20);
556+
557+
ST7701_WRITE(st7701, ST7701_CMD2_BK1_SPD1, 0x78);
558+
559+
ST7701_WRITE(st7701, ST7701_CMD2_BK1_SPD2, 0x78);
560+
561+
ST7701_WRITE(st7701, ST7701_CMD2_BK1_MIPISET1, 0x88);
562+
563+
ST7701_WRITE(st7701, 0xE0, 0x0, 0x0, 0x2);
564+
565+
ST7701_WRITE(st7701, 0xE1,
566+
0x3, 0xA0, 0x0, 0x0, 0x4, 0xA0, 0x0, 0x0,
567+
0x0, 0x20, 0x20);
568+
569+
ST7701_WRITE(st7701, 0xE2,
570+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
571+
0x0, 0x0, 0x0, 0x0, 0x0);
572+
573+
ST7701_WRITE(st7701, 0xE3, 0x0, 0x0, 0x11, 0x0);
574+
575+
ST7701_WRITE(st7701, 0xE4, 0x22, 0x0);
576+
577+
ST7701_WRITE(st7701, 0xE5,
578+
0x5, 0xEC, 0xA0, 0xA0, 0x7, 0xEE, 0xA0, 0xA0,
579+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
580+
581+
ST7701_WRITE(st7701, 0xE6, 0x0, 0x0, 0x11, 0x0);
582+
583+
ST7701_WRITE(st7701, 0xE7, 0x22, 0x0);
584+
585+
ST7701_WRITE(st7701, 0xE8,
586+
0x6, 0xED, 0xA0, 0xA0, 0x8, 0xEF, 0xA0, 0xA0,
587+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
588+
589+
ST7701_WRITE(st7701, 0xEB,
590+
0x0, 0x0, 0x40, 0x40, 0x0, 0x0, 0x0);
591+
592+
ST7701_WRITE(st7701, 0xED,
593+
0xFF, 0xFF, 0xFF, 0xBA, 0xA, 0xBF, 0x45, 0xFF,
594+
0xFF, 0x54, 0xFB, 0xA0, 0xAB, 0xFF, 0xFF, 0xFF);
595+
596+
ST7701_WRITE(st7701, 0xEF, 0x10, 0xD, 0x4, 0x8, 0x3F, 0x1F);
597+
598+
st7701_switch_cmd_bkx(st7701, true, 3);
599+
600+
ST7701_WRITE(st7701, 0xEF, 0x8);
601+
602+
st7701_switch_cmd_bkx(st7701, false, 0);
603+
604+
ST7701_WRITE(st7701, 0xCD, 0x8); /* RGB format COLCTRL */
605+
606+
ST7701_WRITE(st7701, 0x36, 0x8); /* MadCtl */
607+
608+
ST7701_WRITE(st7701, 0x3A, 0x66); /* Colmod */
609+
610+
ST7701_WRITE(st7701, MIPI_DCS_EXIT_SLEEP_MODE);
611+
}
612+
523613
static void wf40eswaa6mnn0_gip_sequence(struct st7701 *st7701)
524614
{
525615
ST7701_WRITE(st7701, 0xE0, 0x00, 0x28, 0x02);
@@ -631,6 +721,11 @@ static int st7701_get_modes(struct drm_panel *panel,
631721
drm_mode_set_name(mode);
632722
drm_mode_probed_add(connector, mode);
633723

724+
if (st7701->desc->mediabus_format)
725+
drm_display_info_set_bus_formats(&connector->display_info,
726+
&st7701->desc->mediabus_format,
727+
1);
728+
634729
connector->display_info.width_mm = desc_mode->width_mm;
635730
connector->display_info.height_mm = desc_mode->height_mm;
636731

@@ -1157,6 +1252,90 @@ static const struct st7701_panel_desc rg28xx_desc = {
11571252
.gip_sequence = rg28xx_gip_sequence,
11581253
};
11591254

1255+
static const struct drm_display_mode txw210001b0_mode = {
1256+
.clock = 19200,
1257+
1258+
.hdisplay = 480,
1259+
.hsync_start = 480 + 10,
1260+
.hsync_end = 480 + 10 + 16,
1261+
.htotal = 480 + 10 + 16 + 56,
1262+
1263+
.vdisplay = 480,
1264+
.vsync_start = 480 + 15,
1265+
.vsync_end = 480 + 15 + 60,
1266+
.vtotal = 480 + 15 + 60 + 15,
1267+
1268+
.width_mm = 53,
1269+
.height_mm = 53,
1270+
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
1271+
1272+
.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
1273+
};
1274+
1275+
static const struct st7701_panel_desc txw210001b0_desc = {
1276+
.mode = &txw210001b0_mode,
1277+
.mediabus_format = MEDIA_BUS_FMT_RGB888_1X24,
1278+
.pv_gamma = {
1279+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1280+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0x2),
1281+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1282+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0x13),
1283+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1284+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x1b),
1285+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0xd),
1286+
1287+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1288+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x10),
1289+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x5),
1290+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x8),
1291+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x7),
1292+
1293+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x7),
1294+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x24),
1295+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),
1296+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1297+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x11),
1298+
1299+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe),
1300+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1301+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2c),
1302+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1303+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x33),
1304+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1305+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1d)
1306+
},
1307+
.nv_gamma = {
1308+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1309+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0x5),
1310+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1311+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0x13),
1312+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0x0) |
1313+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x1b),
1314+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0xd),
1315+
1316+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1317+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11),
1318+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x5),
1319+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x8),
1320+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x7),
1321+
1322+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x7),
1323+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x24),
1324+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),
1325+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1326+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x11),
1327+
1328+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe),
1329+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1330+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2c),
1331+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1332+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x33),
1333+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1334+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1d)
1335+
},
1336+
.gip_sequence = txw210001b0_gip_sequence,
1337+
};
1338+
11601339
static const struct drm_display_mode wf40eswaa6mnn0_mode = {
11611340
.clock = 18306,
11621341

@@ -1258,6 +1437,70 @@ static const struct st7701_panel_desc wf40eswaa6mnn0_desc = {
12581437
.gip_sequence = wf40eswaa6mnn0_gip_sequence,
12591438
};
12601439

1440+
static const struct st7701_panel_desc hyperpixel2r_desc = {
1441+
.mode = &txw210001b0_mode,
1442+
.mediabus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI,
1443+
.pv_gamma = {
1444+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1445+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0x2),
1446+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1447+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0x13),
1448+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1449+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x1b),
1450+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0xd),
1451+
1452+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1453+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x10),
1454+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x5),
1455+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x8),
1456+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x7),
1457+
1458+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x7),
1459+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x24),
1460+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),
1461+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1462+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x11),
1463+
1464+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe),
1465+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1466+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2c),
1467+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1468+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x33),
1469+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1470+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1d)
1471+
},
1472+
.nv_gamma = {
1473+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1474+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0x5),
1475+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1476+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0x13),
1477+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0x0) |
1478+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x1b),
1479+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0xd),
1480+
1481+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1482+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11),
1483+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x5),
1484+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x8),
1485+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x7),
1486+
1487+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x7),
1488+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x24),
1489+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),
1490+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1491+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x11),
1492+
1493+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe),
1494+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1495+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2c),
1496+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1497+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x33),
1498+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1499+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1d)
1500+
},
1501+
.gip_sequence = txw210001b0_gip_sequence,
1502+
};
1503+
12611504
static void st7701_cleanup(void *data)
12621505
{
12631506
struct st7701 *st7701 = (struct st7701 *)data;
@@ -1290,7 +1533,7 @@ static int st7701_probe(struct device *dev, int connector_type)
12901533
if (ret < 0)
12911534
return ret;
12921535

1293-
st7701->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
1536+
st7701->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
12941537
if (IS_ERR(st7701->reset)) {
12951538
dev_err(dev, "Couldn't get our reset GPIO\n");
12961539
return PTR_ERR(st7701->reset);
@@ -1395,12 +1638,16 @@ MODULE_DEVICE_TABLE(of, st7701_dsi_of_match);
13951638

13961639
static const struct of_device_id st7701_spi_of_match[] = {
13971640
{ .compatible = "anbernic,rg28xx-panel", .data = &rg28xx_desc },
1641+
{ .compatible = "txw,txw210001b0", .data = &txw210001b0_desc },
1642+
{ .compatible = "pimoroni,hyperpixel2round", .data = &hyperpixel2r_desc },
13981643
{ /* sentinel */ }
13991644
};
14001645
MODULE_DEVICE_TABLE(of, st7701_spi_of_match);
14011646

14021647
static const struct spi_device_id st7701_spi_ids[] = {
14031648
{ "rg28xx-panel" },
1649+
{ "txw210001b0" },
1650+
{ "hyperpixel2round" },
14041651
{ /* sentinel */ }
14051652
};
14061653
MODULE_DEVICE_TABLE(spi, st7701_spi_ids);

0 commit comments

Comments
 (0)