Skip to content

Commit 21b4101

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 <[email protected]> Signed-off-by: Dave Stevenson <[email protected]>
1 parent 957fc9f commit 21b4101

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 int st7701_prepare(struct drm_panel *panel)
524614
{
525615
struct st7701 *st7701 = panel_to_st7701(panel);
@@ -609,6 +699,11 @@ static int st7701_get_modes(struct drm_panel *panel,
609699
drm_mode_set_name(mode);
610700
drm_mode_probed_add(connector, mode);
611701

702+
if (st7701->desc->mediabus_format)
703+
drm_display_info_set_bus_formats(&connector->display_info,
704+
&st7701->desc->mediabus_format,
705+
1);
706+
612707
connector->display_info.width_mm = desc_mode->width_mm;
613708
connector->display_info.height_mm = desc_mode->height_mm;
614709

@@ -1135,6 +1230,154 @@ static const struct st7701_panel_desc rg28xx_desc = {
11351230
.gip_sequence = rg28xx_gip_sequence,
11361231
};
11371232

1233+
static const struct drm_display_mode txw210001b0_mode = {
1234+
.clock = 19200,
1235+
1236+
.hdisplay = 480,
1237+
.hsync_start = 480 + 10,
1238+
.hsync_end = 480 + 10 + 16,
1239+
.htotal = 480 + 10 + 16 + 56,
1240+
1241+
.vdisplay = 480,
1242+
.vsync_start = 480 + 15,
1243+
.vsync_end = 480 + 15 + 60,
1244+
.vtotal = 480 + 15 + 60 + 15,
1245+
1246+
.width_mm = 53,
1247+
.height_mm = 53,
1248+
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
1249+
1250+
.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
1251+
};
1252+
1253+
static const struct st7701_panel_desc txw210001b0_desc = {
1254+
.mode = &txw210001b0_mode,
1255+
.mediabus_format = MEDIA_BUS_FMT_RGB888_1X24,
1256+
.pv_gamma = {
1257+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1258+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0x2),
1259+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1260+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0x13),
1261+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1262+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x1b),
1263+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0xd),
1264+
1265+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1266+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x10),
1267+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x5),
1268+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x8),
1269+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x7),
1270+
1271+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x7),
1272+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x24),
1273+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),
1274+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1275+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x11),
1276+
1277+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe),
1278+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1279+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2c),
1280+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1281+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x33),
1282+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1283+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1d)
1284+
},
1285+
.nv_gamma = {
1286+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1287+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0x5),
1288+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1289+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0x13),
1290+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0x0) |
1291+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x1b),
1292+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0xd),
1293+
1294+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1295+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11),
1296+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x5),
1297+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x8),
1298+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x7),
1299+
1300+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x7),
1301+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x24),
1302+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),
1303+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1304+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x11),
1305+
1306+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe),
1307+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1308+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2c),
1309+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1310+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x33),
1311+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1312+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1d)
1313+
},
1314+
.gip_sequence = txw210001b0_gip_sequence,
1315+
};
1316+
1317+
static const struct st7701_panel_desc hyperpixel2r_desc = {
1318+
.mode = &txw210001b0_mode,
1319+
.mediabus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI,
1320+
.pv_gamma = {
1321+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1322+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0x2),
1323+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1324+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0x13),
1325+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1326+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x1b),
1327+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0xd),
1328+
1329+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1330+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x10),
1331+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x5),
1332+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x8),
1333+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x7),
1334+
1335+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x7),
1336+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x24),
1337+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),
1338+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1339+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x11),
1340+
1341+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe),
1342+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1343+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2c),
1344+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1345+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x33),
1346+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1347+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1d)
1348+
},
1349+
.nv_gamma = {
1350+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1351+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC0_MASK, 0x5),
1352+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1353+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC4_MASK, 0x13),
1354+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0x0) |
1355+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC8_MASK, 0x1b),
1356+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC16_MASK, 0xd),
1357+
1358+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1359+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11),
1360+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC52_MASK, 0x5),
1361+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC80_MASK, 0x8),
1362+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC108_MASK, 0x7),
1363+
1364+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC147_MASK, 0x7),
1365+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC175_MASK, 0x24),
1366+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),
1367+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1368+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC231_MASK, 0x11),
1369+
1370+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe),
1371+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1372+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2c),
1373+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1374+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC251_MASK, 0x33),
1375+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
1376+
CFIELD_PREP(ST7701_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1d)
1377+
},
1378+
.gip_sequence = txw210001b0_gip_sequence,
1379+
};
1380+
11381381
static void st7701_cleanup(void *data)
11391382
{
11401383
struct st7701 *st7701 = (struct st7701 *)data;
@@ -1166,7 +1409,7 @@ static int st7701_probe(struct device *dev, int connector_type)
11661409
if (ret < 0)
11671410
return ret;
11681411

1169-
st7701->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
1412+
st7701->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
11701413
if (IS_ERR(st7701->reset)) {
11711414
dev_err(dev, "Couldn't get our reset GPIO\n");
11721415
return PTR_ERR(st7701->reset);
@@ -1271,12 +1514,16 @@ MODULE_DEVICE_TABLE(of, st7701_dsi_of_match);
12711514

12721515
static const struct of_device_id st7701_spi_of_match[] = {
12731516
{ .compatible = "anbernic,rg28xx-panel", .data = &rg28xx_desc },
1517+
{ .compatible = "txw,txw210001b0", .data = &txw210001b0_desc },
1518+
{ .compatible = "pimoroni,hyperpixel2round", .data = &hyperpixel2r_desc },
12741519
{ /* sentinel */ }
12751520
};
12761521
MODULE_DEVICE_TABLE(of, st7701_spi_of_match);
12771522

12781523
static const struct spi_device_id st7701_spi_ids[] = {
12791524
{ "rg28xx-panel" },
1525+
{ "txw210001b0" },
1526+
{ "hyperpixel2round" },
12801527
{ /* sentinel */ }
12811528
};
12821529
MODULE_DEVICE_TABLE(spi, st7701_spi_ids);

0 commit comments

Comments
 (0)