// 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");