// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * linux/drivers/video/mmp/panel/tpo_tj032md01bw.c
 * active panel using spi interface to do init
 *
 * Copyright (C) 2012 Marvell Technology Group Ltd.
 * Authors:  Guoqing Li <ligq@marvell.com>
 *          Lisa Du <cldu@marvell.com>
 *          Zhou Zhu <zzhu3@marvell.com>
 */

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/spi/spi.h>
#include <video/mmp_disp.h>

static u16 init[] = {
	0x0801,
	0x0800,
	0x0200,
	0x0304,
	0x040e,
	0x0903,
	0x0b18,
	0x0c53,
	0x0d01,
	0x0ee0,
	0x0f01,
	0x1058,
	0x201e,
	0x210a,
	0x220a,
	0x231e,
	0x2400,
	0x2532,
	0x2600,
	0x27ac,
	0x2904,
	0x2aa2,
	0x2b45,
	0x2c45,
	0x2d15,
	0x2e5a,
	0x2fff,
	0x306b,
	0x310d,
	0x3248,
	0x3382,
	0x34bd,
	0x35e7,
	0x3618,
	0x3794,
	0x3801,
	0x395d,
	0x3aae,
	0x3bff,
	0x07c9,
};

static u16 poweroff[] = {
	0x07d9,
};

struct tpohvga_plat_data {
	void (*plat_onoff)(int status);
	struct spi_device *spi;
};

static void tpohvga_onoff(struct mmp_panel *panel, int status)
{
	struct tpohvga_plat_data *plat = panel->plat_data;
	int ret;

	if (status) {
		plat->plat_onoff(1);

		ret = spi_write(plat->spi, init, sizeof(init));
		if (ret < 0)
			dev_warn(panel->dev, "init cmd failed(%d)\n", ret);
	} else {
		ret = spi_write(plat->spi, poweroff, sizeof(poweroff));
		if (ret < 0)
			dev_warn(panel->dev, "poweroff cmd failed(%d)\n", ret);

		plat->plat_onoff(0);
	}
}

static struct mmp_mode mmp_modes_tpohvga[] = {
	[0] = {
		.pixclock_freq = 10394400,
		.refresh = 60,
		.xres = 320,
		.yres = 480,
		.hsync_len = 10,
		.left_margin = 15,
		.right_margin = 10,
		.vsync_len = 2,
		.upper_margin = 4,
		.lower_margin = 2,
		.invert_pixclock = 1,
		.pix_fmt_out = PIXFMT_RGB565,
	},
};

static int tpohvga_get_modelist(struct mmp_panel *panel,
		struct mmp_mode **modelist)
{
	*modelist = mmp_modes_tpohvga;
	return 1;
}

static struct mmp_panel panel_tpohvga = {
	.name = "tpohvga",
	.panel_type = PANELTYPE_ACTIVE,
	.get_modelist = tpohvga_get_modelist,
	.set_onoff = tpohvga_onoff,
};

static int tpohvga_probe(struct spi_device *spi)
{
	struct mmp_mach_panel_info *mi;
	int ret;
	struct tpohvga_plat_data *plat_data;

	/* get configs from platform data */
	mi = spi->dev.platform_data;
	if (mi == NULL) {
		dev_err(&spi->dev, "%s: no platform data defined\n", __func__);
		return -EINVAL;
	}

	/* setup spi related info */
	spi->bits_per_word = 16;
	ret = spi_setup(spi);
	if (ret < 0) {
		dev_err(&spi->dev, "spi setup failed %d", ret);
		return ret;
	}

	plat_data = kzalloc(sizeof(*plat_data), GFP_KERNEL);
	if (plat_data == NULL)
		return -ENOMEM;

	plat_data->spi = spi;
	plat_data->plat_onoff = mi->plat_set_onoff;
	panel_tpohvga.plat_data = plat_data;
	panel_tpohvga.plat_path_name = mi->plat_path_name;
	panel_tpohvga.dev = &spi->dev;

	mmp_register_panel(&panel_tpohvga);

	return 0;
}

static struct spi_driver panel_tpohvga_driver = {
	.driver		= {
		.name	= "tpo-hvga",
	},
	.probe		= tpohvga_probe,
};
module_spi_driver(panel_tpohvga_driver);

MODULE_AUTHOR("Lisa Du<cldu@marvell.com>");
MODULE_DESCRIPTION("Panel driver for tpohvga");
MODULE_LICENSE("GPL");
