brintos

brintos / linux-shallow public Read only

0
0
Text · 3.2 KiB · a89d925 Raw
141 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * DSI interface to the Samsung S6E63M0 panel.4 * (C) 2019 Linus Walleij5 */6 7#include <linux/module.h>8#include <linux/delay.h>9#include <linux/mod_devicetable.h>10 11#include <drm/drm_mipi_dsi.h>12#include <drm/drm_print.h>13 14#include "panel-samsung-s6e63m0.h"15 16#define MCS_GLOBAL_PARAM	0xb017#define S6E63M0_DSI_MAX_CHUNK	15 /* CMD + 15 bytes max */18 19static int s6e63m0_dsi_dcs_read(struct device *dev, void *trsp,20				const u8 cmd, u8 *data)21{22	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);23	int ret;24 25	ret = mipi_dsi_dcs_read(dsi, cmd, data, 1);26	if (ret < 0) {27		dev_err(dev, "could not read DCS CMD %02x\n", cmd);28		return ret;29	}30 31	dev_dbg(dev, "DSI read CMD %02x = %02x\n", cmd, *data);32 33	return 0;34}35 36static int s6e63m0_dsi_dcs_write(struct device *dev, void *trsp,37				 const u8 *data, size_t len)38{39	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);40	const u8 *seqp = data;41	u8 cmd;42	u8 cmdwritten;43	int remain;44	int chunk;45	int ret;46 47	dev_dbg(dev, "DSI writing dcs seq: %*ph\n", (int)len, data);48 49	/* Pick out and skip past the DCS command */50	cmd = *seqp;51	seqp++;52	cmdwritten = 0;53	remain = len - 1;54	chunk = remain;55 56	/* Send max S6E63M0_DSI_MAX_CHUNK bytes at a time */57	if (chunk > S6E63M0_DSI_MAX_CHUNK)58		chunk = S6E63M0_DSI_MAX_CHUNK;59	ret = mipi_dsi_dcs_write(dsi, cmd, seqp, chunk);60	if (ret < 0) {61		dev_err(dev, "error sending DCS command seq cmd %02x\n", cmd);62		return ret;63	}64	cmdwritten += chunk;65	seqp += chunk;66 67	while (cmdwritten < remain) {68		chunk = remain - cmdwritten;69		if (chunk > S6E63M0_DSI_MAX_CHUNK)70			chunk = S6E63M0_DSI_MAX_CHUNK;71		ret = mipi_dsi_dcs_write(dsi, MCS_GLOBAL_PARAM, &cmdwritten, 1);72		if (ret < 0) {73			dev_err(dev, "error sending CMD %02x global param %02x\n",74				cmd, cmdwritten);75			return ret;76		}77		ret = mipi_dsi_dcs_write(dsi, cmd, seqp, chunk);78		if (ret < 0) {79			dev_err(dev, "error sending CMD %02x chunk\n", cmd);80			return ret;81		}82		cmdwritten += chunk;83		seqp += chunk;84	}85	dev_dbg(dev, "sent command %02x %02x bytes\n", cmd, cmdwritten);86 87	usleep_range(8000, 9000);88 89	return 0;90}91 92static int s6e63m0_dsi_probe(struct mipi_dsi_device *dsi)93{94	struct device *dev = &dsi->dev;95	int ret;96 97	dsi->lanes = 2;98	dsi->format = MIPI_DSI_FMT_RGB888;99	dsi->hs_rate = 349440000;100	dsi->lp_rate = 9600000;101	dsi->mode_flags = MIPI_DSI_MODE_VIDEO |102		MIPI_DSI_MODE_VIDEO_BURST;103 104	ret = s6e63m0_probe(dev, NULL, s6e63m0_dsi_dcs_read,105			    s6e63m0_dsi_dcs_write, true);106	if (ret)107		return ret;108 109	ret = mipi_dsi_attach(dsi);110	if (ret < 0)111		s6e63m0_remove(dev);112 113	return ret;114}115 116static void s6e63m0_dsi_remove(struct mipi_dsi_device *dsi)117{118	mipi_dsi_detach(dsi);119	s6e63m0_remove(&dsi->dev);120}121 122static const struct of_device_id s6e63m0_dsi_of_match[] = {123	{ .compatible = "samsung,s6e63m0" },124	{ /* sentinel */ }125};126MODULE_DEVICE_TABLE(of, s6e63m0_dsi_of_match);127 128static struct mipi_dsi_driver s6e63m0_dsi_driver = {129	.probe			= s6e63m0_dsi_probe,130	.remove			= s6e63m0_dsi_remove,131	.driver			= {132		.name		= "panel-samsung-s6e63m0",133		.of_match_table = s6e63m0_dsi_of_match,134	},135};136module_mipi_dsi_driver(s6e63m0_dsi_driver);137 138MODULE_AUTHOR("Linus Walleij <linusw@kernel.org>");139MODULE_DESCRIPTION("s6e63m0 LCD DSI Driver");140MODULE_LICENSE("GPL v2");141