162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#include <linux/device.h>
462306a36Sopenharmony_ci#include <linux/module.h>
562306a36Sopenharmony_ci#include <linux/spi/spi.h>
662306a36Sopenharmony_ci#include <linux/delay.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <drm/drm_mipi_dbi.h>
962306a36Sopenharmony_ci#include <drm/drm_print.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include "panel-samsung-s6e63m0.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistatic const u8 s6e63m0_dbi_read_commands[] = {
1462306a36Sopenharmony_ci	MCS_READ_ID1,
1562306a36Sopenharmony_ci	MCS_READ_ID2,
1662306a36Sopenharmony_ci	MCS_READ_ID3,
1762306a36Sopenharmony_ci	0, /* sentinel */
1862306a36Sopenharmony_ci};
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic int s6e63m0_spi_dcs_read(struct device *dev, void *trsp,
2162306a36Sopenharmony_ci				const u8 cmd, u8 *data)
2262306a36Sopenharmony_ci{
2362306a36Sopenharmony_ci	struct mipi_dbi *dbi = trsp;
2462306a36Sopenharmony_ci	int ret;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	ret = mipi_dbi_command_read(dbi, cmd, data);
2762306a36Sopenharmony_ci	if (ret)
2862306a36Sopenharmony_ci		dev_err(dev, "error on DBI read command %02x\n", cmd);
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	return ret;
3162306a36Sopenharmony_ci}
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_cistatic int s6e63m0_spi_dcs_write(struct device *dev, void *trsp,
3462306a36Sopenharmony_ci				 const u8 *data, size_t len)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	struct mipi_dbi *dbi = trsp;
3762306a36Sopenharmony_ci	int ret;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	ret = mipi_dbi_command_stackbuf(dbi, data[0], (data + 1), (len - 1));
4062306a36Sopenharmony_ci	usleep_range(300, 310);
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	return ret;
4362306a36Sopenharmony_ci}
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistatic int s6e63m0_spi_probe(struct spi_device *spi)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	struct device *dev = &spi->dev;
4862306a36Sopenharmony_ci	struct mipi_dbi *dbi;
4962306a36Sopenharmony_ci	int ret;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	dbi = devm_kzalloc(dev, sizeof(*dbi), GFP_KERNEL);
5262306a36Sopenharmony_ci	if (!dbi)
5362306a36Sopenharmony_ci		return -ENOMEM;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	ret = mipi_dbi_spi_init(spi, dbi, NULL);
5662306a36Sopenharmony_ci	if (ret)
5762306a36Sopenharmony_ci		return dev_err_probe(dev, ret, "MIPI DBI init failed\n");
5862306a36Sopenharmony_ci	/* Register our custom MCS read commands */
5962306a36Sopenharmony_ci	dbi->read_commands = s6e63m0_dbi_read_commands;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	return s6e63m0_probe(dev, dbi, s6e63m0_spi_dcs_read,
6262306a36Sopenharmony_ci			     s6e63m0_spi_dcs_write, false);
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic void s6e63m0_spi_remove(struct spi_device *spi)
6662306a36Sopenharmony_ci{
6762306a36Sopenharmony_ci	s6e63m0_remove(&spi->dev);
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistatic const struct of_device_id s6e63m0_spi_of_match[] = {
7162306a36Sopenharmony_ci	{ .compatible = "samsung,s6e63m0" },
7262306a36Sopenharmony_ci	{ /* sentinel */ }
7362306a36Sopenharmony_ci};
7462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, s6e63m0_spi_of_match);
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistatic struct spi_driver s6e63m0_spi_driver = {
7762306a36Sopenharmony_ci	.probe			= s6e63m0_spi_probe,
7862306a36Sopenharmony_ci	.remove			= s6e63m0_spi_remove,
7962306a36Sopenharmony_ci	.driver			= {
8062306a36Sopenharmony_ci		.name		= "panel-samsung-s6e63m0",
8162306a36Sopenharmony_ci		.of_match_table = s6e63m0_spi_of_match,
8262306a36Sopenharmony_ci	},
8362306a36Sopenharmony_ci};
8462306a36Sopenharmony_cimodule_spi_driver(s6e63m0_spi_driver);
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ciMODULE_AUTHOR("Paweł Chmiel <pawel.mikolaj.chmiel@gmail.com>");
8762306a36Sopenharmony_ciMODULE_DESCRIPTION("s6e63m0 LCD SPI Driver");
8862306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
89