1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * linux/drivers/video/mmp/panel/tpo_tj032md01bw.c 4 * active panel using spi interface to do init 5 * 6 * Copyright (C) 2012 Marvell Technology Group Ltd. 7 * Authors: Guoqing Li <ligq@marvell.com> 8 * Lisa Du <cldu@marvell.com> 9 * Zhou Zhu <zzhu3@marvell.com> 10 */ 11 12 #include <linux/module.h> 13 #include <linux/moduleparam.h> 14 #include <linux/kernel.h> 15 #include <linux/errno.h> 16 #include <linux/string.h> 17 #include <linux/delay.h> 18 #include <linux/platform_device.h> 19 #include <linux/err.h> 20 #include <linux/spi/spi.h> 21 #include <video/mmp_disp.h> 22 23 static u16 init[] = { 24 0x0801, 25 0x0800, 26 0x0200, 27 0x0304, 28 0x040e, 29 0x0903, 30 0x0b18, 31 0x0c53, 32 0x0d01, 33 0x0ee0, 34 0x0f01, 35 0x1058, 36 0x201e, 37 0x210a, 38 0x220a, 39 0x231e, 40 0x2400, 41 0x2532, 42 0x2600, 43 0x27ac, 44 0x2904, 45 0x2aa2, 46 0x2b45, 47 0x2c45, 48 0x2d15, 49 0x2e5a, 50 0x2fff, 51 0x306b, 52 0x310d, 53 0x3248, 54 0x3382, 55 0x34bd, 56 0x35e7, 57 0x3618, 58 0x3794, 59 0x3801, 60 0x395d, 61 0x3aae, 62 0x3bff, 63 0x07c9, 64 }; 65 66 static u16 poweroff[] = { 67 0x07d9, 68 }; 69 70 struct tpohvga_plat_data { 71 void (*plat_onoff)(int status); 72 struct spi_device *spi; 73 }; 74 75 static void tpohvga_onoff(struct mmp_panel *panel, int status) 76 { 77 struct tpohvga_plat_data *plat = panel->plat_data; 78 int ret; 79 80 if (status) { 81 plat->plat_onoff(1); 82 83 ret = spi_write(plat->spi, init, sizeof(init)); 84 if (ret < 0) 85 dev_warn(panel->dev, "init cmd failed(%d)\n", ret); 86 } else { 87 ret = spi_write(plat->spi, poweroff, sizeof(poweroff)); 88 if (ret < 0) 89 dev_warn(panel->dev, "poweroff cmd failed(%d)\n", ret); 90 91 plat->plat_onoff(0); 92 } 93 } 94 95 static struct mmp_mode mmp_modes_tpohvga[] = { 96 [0] = { 97 .pixclock_freq = 10394400, 98 .refresh = 60, 99 .xres = 320, 100 .yres = 480, 101 .hsync_len = 10, 102 .left_margin = 15, 103 .right_margin = 10, 104 .vsync_len = 2, 105 .upper_margin = 4, 106 .lower_margin = 2, 107 .invert_pixclock = 1, 108 .pix_fmt_out = PIXFMT_RGB565, 109 }, 110 }; 111 112 static int tpohvga_get_modelist(struct mmp_panel *panel, 113 struct mmp_mode **modelist) 114 { 115 *modelist = mmp_modes_tpohvga; 116 return 1; 117 } 118 119 static struct mmp_panel panel_tpohvga = { 120 .name = "tpohvga", 121 .panel_type = PANELTYPE_ACTIVE, 122 .get_modelist = tpohvga_get_modelist, 123 .set_onoff = tpohvga_onoff, 124 }; 125 126 static int tpohvga_probe(struct spi_device *spi) 127 { 128 struct mmp_mach_panel_info *mi; 129 int ret; 130 struct tpohvga_plat_data *plat_data; 131 132 /* get configs from platform data */ 133 mi = spi->dev.platform_data; 134 if (mi == NULL) { 135 dev_err(&spi->dev, "%s: no platform data defined\n", __func__); 136 return -EINVAL; 137 } 138 139 /* setup spi related info */ 140 spi->bits_per_word = 16; 141 ret = spi_setup(spi); 142 if (ret < 0) { 143 dev_err(&spi->dev, "spi setup failed %d", ret); 144 return ret; 145 } 146 147 plat_data = kzalloc(sizeof(*plat_data), GFP_KERNEL); 148 if (plat_data == NULL) 149 return -ENOMEM; 150 151 plat_data->spi = spi; 152 plat_data->plat_onoff = mi->plat_set_onoff; 153 panel_tpohvga.plat_data = plat_data; 154 panel_tpohvga.plat_path_name = mi->plat_path_name; 155 panel_tpohvga.dev = &spi->dev; 156 157 mmp_register_panel(&panel_tpohvga); 158 159 return 0; 160 } 161 162 static struct spi_driver panel_tpohvga_driver = { 163 .driver = { 164 .name = "tpo-hvga", 165 }, 166 .probe = tpohvga_probe, 167 }; 168 module_spi_driver(panel_tpohvga_driver); 169 170 MODULE_AUTHOR("Lisa Du<cldu@marvell.com>"); 171 MODULE_DESCRIPTION("Panel driver for tpohvga"); 172 MODULE_LICENSE("GPL"); 173