brintos

brintos / linux-shallow public Read only

0
0
Text · 19.4 KiB · 104b229 Raw
519 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2021, Linaro Limited4 *5 * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:6 *   Copyright (c) 2013, The Linux Foundation. All rights reserved.7 */8 9#include <linux/backlight.h>10#include <linux/delay.h>11#include <linux/gpio/consumer.h>12#include <linux/module.h>13#include <linux/of.h>14#include <linux/regulator/consumer.h>15 16#include <drm/drm_mipi_dsi.h>17#include <drm/drm_modes.h>18#include <drm/drm_panel.h>19 20struct truly_nt35521 {21	struct drm_panel panel;22	struct mipi_dsi_device *dsi;23	struct regulator_bulk_data supplies[2];24	struct gpio_desc *reset_gpio;25	struct gpio_desc *blen_gpio;26};27 28#define NT35521_DCS_SWITCH_PAGE	0xf029 30#define nt35521_switch_page(dsi_ctx, page) \31	mipi_dsi_dcs_write_seq_multi(dsi_ctx, NT35521_DCS_SWITCH_PAGE, \32				     0x55, 0xaa, 0x52, 0x08, (page))33 34static inline35struct truly_nt35521 *to_truly_nt35521(struct drm_panel *panel)36{37	return container_of(panel, struct truly_nt35521, panel);38}39 40static void truly_nt35521_reset(struct truly_nt35521 *ctx)41{42	gpiod_set_value_cansleep(ctx->reset_gpio, 1);43	usleep_range(1000, 2000);44	gpiod_set_value_cansleep(ctx->reset_gpio, 1);45	usleep_range(10000, 11000);46	gpiod_set_value_cansleep(ctx->reset_gpio, 0);47	msleep(150);48}49 50static int truly_nt35521_on(struct truly_nt35521 *ctx)51{52	struct mipi_dsi_device *dsi = ctx->dsi;53	struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };54 55	dsi->mode_flags |= MIPI_DSI_MODE_LPM;56 57	nt35521_switch_page(&dsi_ctx, 0x00);58	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xff, 0xaa, 0x55, 0xa5, 0x80);59	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x11, 0x00);60	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf7, 0x20, 0x00);61	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x01);62	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x21);63	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x01, 0xa0, 0x10, 0x08, 0x01);64	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb8, 0x01, 0x02, 0x0c, 0x02);65	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x11, 0x11);66	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x00, 0x00);67	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb6, 0x02);68 69	nt35521_switch_page(&dsi_ctx, 0x01);70	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x09, 0x09);71	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x09, 0x09);72	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x8c, 0x00);73	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x8c, 0x00);74	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xca, 0x00);75	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x04);76	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbe, 0xb5);77	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x35, 0x35);78	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4, 0x25, 0x25);79	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb9, 0x43, 0x43);80	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, 0x24, 0x24);81 82	nt35521_switch_page(&dsi_ctx, 0x02);83	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xee, 0x03);84	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0,85					 0x00, 0xb2, 0x00, 0xb3, 0x00, 0xb6, 0x00, 0xc3,86					 0x00, 0xce, 0x00, 0xe1, 0x00, 0xf3, 0x01, 0x11);87	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1,88					 0x01, 0x2e, 0x01, 0x5c, 0x01, 0x82, 0x01, 0xc3,89					 0x01, 0xfe, 0x02, 0x00, 0x02, 0x37, 0x02, 0x77);90	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb2,91					 0x02, 0xa1, 0x02, 0xd7, 0x02, 0xfe, 0x03, 0x2c,92					 0x03, 0x4b, 0x03, 0x63, 0x03, 0x8f, 0x03, 0x90);93	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x03, 0x96, 0x03, 0x98);94	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4,95					 0x00, 0x81, 0x00, 0x8b, 0x00, 0x9c, 0x00, 0xa9,96					 0x00, 0xb5, 0x00, 0xcb, 0x00, 0xdf, 0x01, 0x02);97	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb5,98					 0x01, 0x1f, 0x01, 0x51, 0x01, 0x7a, 0x01, 0xbf,99					 0x01, 0xfa, 0x01, 0xfc, 0x02, 0x34, 0x02, 0x76);100	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb6,101					 0x02, 0x9f, 0x02, 0xd7, 0x02, 0xfc, 0x03, 0x2c,102					 0x03, 0x4a, 0x03, 0x63, 0x03, 0x8f, 0x03, 0xa2);103	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb7, 0x03, 0xb8, 0x03, 0xba);104	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb8,105					 0x00, 0x01, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x2a,106					 0x00, 0x41, 0x00, 0x67, 0x00, 0x87, 0x00, 0xb9);107	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb9,108					 0x00, 0xe2, 0x01, 0x22, 0x01, 0x54, 0x01, 0xa3,109					 0x01, 0xe6, 0x01, 0xe7, 0x02, 0x24, 0x02, 0x67);110	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba,111					 0x02, 0x93, 0x02, 0xcd, 0x02, 0xf6, 0x03, 0x31,112					 0x03, 0x6c, 0x03, 0xe9, 0x03, 0xef, 0x03, 0xf4);113	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x03, 0xf6, 0x03, 0xf7);114 115	nt35521_switch_page(&dsi_ctx, 0x03);116	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x22, 0x00);117	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x22, 0x00);118	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb2, 0x05, 0x00, 0x60, 0x00, 0x00);119	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x05, 0x00, 0x60, 0x00, 0x00);120	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4, 0x05, 0x00, 0x60, 0x00, 0x00);121	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb5, 0x05, 0x00, 0x60, 0x00, 0x00);122	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, 0x53, 0x00, 0x60, 0x00, 0x00);123	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x53, 0x00, 0x60, 0x00, 0x00);124	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x53, 0x00, 0x60, 0x00, 0x00);125	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x53, 0x00, 0x60, 0x00, 0x00);126	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x00, 0x34, 0x00, 0x00);127	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x00, 0x00, 0x34, 0x00);128	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc2, 0x00, 0x00, 0x34, 0x00);129	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc3, 0x00, 0x00, 0x34, 0x00);130	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x60);131	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0xc0);132	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc6, 0x00);133	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc7, 0x00);134 135	nt35521_switch_page(&dsi_ctx, 0x05);136	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x17, 0x06);137	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x17, 0x06);138	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb2, 0x17, 0x06);139	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x17, 0x06);140	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4, 0x17, 0x06);141	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb5, 0x17, 0x06);142	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb6, 0x17, 0x06);143	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb7, 0x17, 0x06);144	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb8, 0x00);145	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb9, 0x00, 0x03);146	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, 0x00, 0x00);147	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x02, 0x03);148	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x02, 0x03);149	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x03, 0x03, 0x00, 0x03, 0x03);150	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x0b);151	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x09);152	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc2, 0xa6);153	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc3, 0x05);154	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x00);155	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x02);156	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc6, 0x22);157	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc7, 0x03);158	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc8, 0x07, 0x20);159	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc9, 0x03, 0x20);160	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xca, 0x01, 0x60);161	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, 0x01, 0x60);162	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, 0x00, 0x00, 0x02);163	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcd, 0x00, 0x00, 0x02);164	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, 0x00, 0x00, 0x02);165	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, 0x00, 0x00, 0x02);166	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd1, 0x00, 0x05, 0x01, 0x07, 0x10);167	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd2, 0x10, 0x05, 0x05, 0x03, 0x10);168	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd3, 0x20, 0x00, 0x43, 0x07, 0x10);169	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd4, 0x30, 0x00, 0x43, 0x07, 0x10);170	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd0,171					 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);172	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd5,173					 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,174					 0x00, 0x00, 0x00);175	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd6,176					 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,177					 0x00, 0x00, 0x00);178	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd7,179					 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,180					 0x00, 0x00, 0x00);181	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);182	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe5, 0x06);183	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe6, 0x06);184	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe7, 0x00);185	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe8, 0x06);186	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe9, 0x06);187	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xea, 0x06);188	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xeb, 0x00);189	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xec, 0x00);190	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xed, 0x30);191 192	nt35521_switch_page(&dsi_ctx, 0x06);193	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb0, 0x31, 0x31);194	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x31, 0x31);195	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb2, 0x2d, 0x2e);196	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb3, 0x31, 0x34);197	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb4, 0x29, 0x2a);198	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb5, 0x12, 0x10);199	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb6, 0x18, 0x16);200	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb7, 0x00, 0x02);201	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb8, 0x08, 0x31);202	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb9, 0x31, 0x31);203	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xba, 0x31, 0x31);204	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbb, 0x31, 0x08);205	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbc, 0x03, 0x01);206	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbd, 0x17, 0x19);207	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbe, 0x11, 0x13);208	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xbf, 0x2a, 0x29);209	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc0, 0x34, 0x31);210	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc1, 0x2e, 0x2d);211	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc2, 0x31, 0x31);212	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc3, 0x31, 0x31);213	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc4, 0x31, 0x31);214	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc5, 0x31, 0x31);215	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc6, 0x2e, 0x2d);216	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc7, 0x31, 0x34);217	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc8, 0x29, 0x2a);218	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xc9, 0x17, 0x19);219	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xca, 0x11, 0x13);220	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcb, 0x03, 0x01);221	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcc, 0x08, 0x31);222	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcd, 0x31, 0x31);223	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xce, 0x31, 0x31);224	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xcf, 0x31, 0x08);225	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd0, 0x00, 0x02);226	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd1, 0x12, 0x10);227	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd2, 0x18, 0x16);228	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd3, 0x2a, 0x29);229	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd4, 0x34, 0x31);230	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd5, 0x2d, 0x2e);231	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd6, 0x31, 0x31);232	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd7, 0x31, 0x31);233	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe5, 0x31, 0x31);234	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe6, 0x31, 0x31);235	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);236	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00);237	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xe7, 0x00);238	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x02);239	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf7, 0x47);240	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x0a);241	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf7, 0x02);242	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x17);243	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf4, 0x60);244	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x01);245	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf9, 0x46);246	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x6f, 0x11);247	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf3, 0x01);248	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x35, 0x00);249 250	nt35521_switch_page(&dsi_ctx, 0x00);251	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xd9, 0x02, 0x03, 0x00);252	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);253 254	nt35521_switch_page(&dsi_ctx, 0x00);255	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xb1, 0x6c, 0x21);256	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0xf0, 0x55, 0xaa, 0x52, 0x00, 0x00);257	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x35, 0x00);258 259	mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);260	mipi_dsi_msleep(&dsi_ctx, 120);261	mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);262 263	usleep_range(1000, 2000);264 265	mipi_dsi_generic_write_seq_multi(&dsi_ctx, 0x53, 0x24);266 267	return dsi_ctx.accum_err;268}269 270static int truly_nt35521_off(struct truly_nt35521 *ctx)271{272	struct mipi_dsi_device *dsi = ctx->dsi;273	struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };274 275	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;276 277	mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);278	mipi_dsi_msleep(&dsi_ctx, 50);279	mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);280	mipi_dsi_msleep(&dsi_ctx, 150);281 282	return dsi_ctx.accum_err;283}284 285static int truly_nt35521_prepare(struct drm_panel *panel)286{287	struct truly_nt35521 *ctx = to_truly_nt35521(panel);288	struct device *dev = &ctx->dsi->dev;289	int ret;290 291	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);292	if (ret < 0) {293		dev_err(dev, "Failed to enable regulators: %d\n", ret);294		return ret;295	}296 297	truly_nt35521_reset(ctx);298 299	ret = truly_nt35521_on(ctx);300	if (ret < 0) {301		dev_err(dev, "Failed to initialize panel: %d\n", ret);302		gpiod_set_value_cansleep(ctx->reset_gpio, 1);303		return ret;304	}305 306	return 0;307}308 309static int truly_nt35521_unprepare(struct drm_panel *panel)310{311	struct truly_nt35521 *ctx = to_truly_nt35521(panel);312	struct device *dev = &ctx->dsi->dev;313	int ret;314 315	ret = truly_nt35521_off(ctx);316	if (ret < 0)317		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);318 319	gpiod_set_value_cansleep(ctx->reset_gpio, 1);320	regulator_bulk_disable(ARRAY_SIZE(ctx->supplies),321			       ctx->supplies);322 323	return 0;324}325 326static int truly_nt35521_enable(struct drm_panel *panel)327{328	struct truly_nt35521 *ctx = to_truly_nt35521(panel);329 330	gpiod_set_value_cansleep(ctx->blen_gpio, 1);331 332	return 0;333}334 335static int truly_nt35521_disable(struct drm_panel *panel)336{337	struct truly_nt35521 *ctx = to_truly_nt35521(panel);338 339	gpiod_set_value_cansleep(ctx->blen_gpio, 0);340 341	return 0;342}343 344static const struct drm_display_mode truly_nt35521_mode = {345	.clock = (720 + 232 + 20 + 112) * (1280 + 18 + 1 + 18) * 60 / 1000,346	.hdisplay = 720,347	.hsync_start = 720 + 232,348	.hsync_end = 720 + 232 + 20,349	.htotal = 720 + 232 + 20 + 112,350	.vdisplay = 1280,351	.vsync_start = 1280 + 18,352	.vsync_end = 1280 + 18 + 1,353	.vtotal = 1280 + 18 + 1 + 18,354	.width_mm = 65,355	.height_mm = 116,356};357 358static int truly_nt35521_get_modes(struct drm_panel *panel,359				   struct drm_connector *connector)360{361	struct drm_display_mode *mode;362 363	mode = drm_mode_duplicate(connector->dev, &truly_nt35521_mode);364	if (!mode)365		return -ENOMEM;366 367	drm_mode_set_name(mode);368 369	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;370	connector->display_info.width_mm = mode->width_mm;371	connector->display_info.height_mm = mode->height_mm;372	drm_mode_probed_add(connector, mode);373 374	return 1;375}376 377static const struct drm_panel_funcs truly_nt35521_panel_funcs = {378	.prepare = truly_nt35521_prepare,379	.unprepare = truly_nt35521_unprepare,380	.enable = truly_nt35521_enable,381	.disable = truly_nt35521_disable,382	.get_modes = truly_nt35521_get_modes,383};384 385static int truly_nt35521_bl_update_status(struct backlight_device *bl)386{387	struct mipi_dsi_device *dsi = bl_get_data(bl);388	u16 brightness = backlight_get_brightness(bl);389	int ret;390 391	ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);392	if (ret < 0)393		return ret;394 395	return 0;396}397 398static int truly_nt35521_bl_get_brightness(struct backlight_device *bl)399{400	struct mipi_dsi_device *dsi = bl_get_data(bl);401	u16 brightness;402	int ret;403 404	ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);405	if (ret < 0)406		return ret;407 408	return brightness & 0xff;409}410 411static const struct backlight_ops truly_nt35521_bl_ops = {412	.update_status = truly_nt35521_bl_update_status,413	.get_brightness = truly_nt35521_bl_get_brightness,414};415 416static struct backlight_device *417truly_nt35521_create_backlight(struct mipi_dsi_device *dsi)418{419	struct device *dev = &dsi->dev;420	const struct backlight_properties props = {421		.type = BACKLIGHT_RAW,422		.brightness = 255,423		.max_brightness = 255,424	};425 426	return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,427					      &truly_nt35521_bl_ops, &props);428}429 430static int truly_nt35521_probe(struct mipi_dsi_device *dsi)431{432	struct device *dev = &dsi->dev;433	struct truly_nt35521 *ctx;434	int ret;435 436	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);437	if (!ctx)438		return -ENOMEM;439 440	ctx->supplies[0].supply = "positive5";441	ctx->supplies[1].supply = "negative5";442	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),443				      ctx->supplies);444	if (ret < 0) {445		dev_err(dev, "Failed to get regulators: %d\n", ret);446		return ret;447	}448 449	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);450	if (IS_ERR(ctx->reset_gpio))451		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),452				     "Failed to get reset-gpios\n");453 454	ctx->blen_gpio = devm_gpiod_get(dev, "backlight", GPIOD_OUT_LOW);455	if (IS_ERR(ctx->blen_gpio))456		return dev_err_probe(dev, PTR_ERR(ctx->blen_gpio),457				     "Failed to get backlight-gpios\n");458 459	ctx->dsi = dsi;460	mipi_dsi_set_drvdata(dsi, ctx);461 462	dsi->lanes = 4;463	dsi->format = MIPI_DSI_FMT_RGB888;464	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |465			  MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_NO_EOT_PACKET |466			  MIPI_DSI_CLOCK_NON_CONTINUOUS;467 468	drm_panel_init(&ctx->panel, dev, &truly_nt35521_panel_funcs,469		       DRM_MODE_CONNECTOR_DSI);470 471	ctx->panel.backlight = truly_nt35521_create_backlight(dsi);472	if (IS_ERR(ctx->panel.backlight))473		return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),474				     "Failed to create backlight\n");475 476	drm_panel_add(&ctx->panel);477 478	ret = mipi_dsi_attach(dsi);479	if (ret < 0) {480		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);481		drm_panel_remove(&ctx->panel);482		return ret;483	}484 485	return 0;486}487 488static void truly_nt35521_remove(struct mipi_dsi_device *dsi)489{490	struct truly_nt35521 *ctx = mipi_dsi_get_drvdata(dsi);491	int ret;492 493	ret = mipi_dsi_detach(dsi);494	if (ret < 0)495		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);496 497	drm_panel_remove(&ctx->panel);498}499 500static const struct of_device_id truly_nt35521_of_match[] = {501	{ .compatible = "sony,tulip-truly-nt35521" },502	{ /* sentinel */ }503};504MODULE_DEVICE_TABLE(of, truly_nt35521_of_match);505 506static struct mipi_dsi_driver truly_nt35521_driver = {507	.probe = truly_nt35521_probe,508	.remove = truly_nt35521_remove,509	.driver = {510		.name = "panel-truly-nt35521",511		.of_match_table = truly_nt35521_of_match,512	},513};514module_mipi_dsi_driver(truly_nt35521_driver);515 516MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");517MODULE_DESCRIPTION("DRM driver for Sony Tulip Truly NT35521 panel");518MODULE_LICENSE("GPL v2");519