root/drivers/video/fbdev/mmp/panel/tpo_tj032md01bw.c
// 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_obj(*plat_data);
        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");