^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * tdo24m - SPI-based drivers for Toppoly TDO24M series LCD panels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2008 Marvell International Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Eric Miao <eric.miao@marvell.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/spi/spi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/spi/tdo24m.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/lcd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define TDO24M_SPI_BUFF_SIZE (4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define MODE_QVGA 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define MODE_VGA 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct tdo24m {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct spi_device *spi_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct lcd_device *lcd_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct spi_message msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct spi_transfer xfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) uint8_t *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) int (*adj_mode)(struct tdo24m *lcd, int mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) int color_invert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* use bit 30, 31 as the indicator of command parameter number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define CMD0(x) ((0 << 30) | (x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define CMD1(x, x1) ((1 << 30) | ((x) << 9) | 0x100 | (x1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define CMD2(x, x1, x2) ((2 << 30) | ((x) << 18) | 0x20000 |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) ((x1) << 9) | 0x100 | (x2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define CMD_NULL (-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static const uint32_t lcd_panel_reset[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) CMD0(0x1), /* reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) CMD0(0x0), /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) CMD0(0x0), /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) CMD0(0x0), /* nop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) CMD_NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static const uint32_t lcd_panel_on[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) CMD0(0x29), /* Display ON */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) CMD2(0xB8, 0xFF, 0xF9), /* Output Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) CMD0(0x11), /* Sleep out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) CMD1(0xB0, 0x16), /* Wake */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) CMD_NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static const uint32_t lcd_panel_off[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) CMD0(0x28), /* Display OFF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) CMD2(0xB8, 0x80, 0x02), /* Output Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) CMD0(0x10), /* Sleep in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) CMD1(0xB0, 0x00), /* Deep stand by in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) CMD_NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static const uint32_t lcd_vga_pass_through_tdo24m[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) CMD1(0xB0, 0x16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) CMD1(0xBC, 0x80),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) CMD1(0xE1, 0x00),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) CMD1(0x36, 0x50),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) CMD1(0x3B, 0x00),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) CMD_NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static const uint32_t lcd_qvga_pass_through_tdo24m[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) CMD1(0xB0, 0x16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) CMD1(0xBC, 0x81),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) CMD1(0xE1, 0x00),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) CMD1(0x36, 0x50),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) CMD1(0x3B, 0x22),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) CMD_NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static const uint32_t lcd_vga_transfer_tdo24m[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) CMD1(0xcf, 0x02), /* Blanking period control (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) CMD1(0xd1, 0x01), /* CKV timing control on/off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) CMD2(0xd2, 0x14, 0x00), /* CKV 1,2 timing control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) CMD2(0xd3, 0x1a, 0x0f), /* OEV timing control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) CMD2(0xd4, 0x1f, 0xaf), /* ASW timing control (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) CMD1(0xd5, 0x14), /* ASW timing control (2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) CMD0(0x21), /* Invert for normally black display */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) CMD0(0x29), /* Display on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) CMD_NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static const uint32_t lcd_qvga_transfer[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) CMD1(0xd6, 0x02), /* Blanking period control (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) CMD2(0xd7, 0x08, 0x04), /* Blanking period control (2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) CMD1(0xd8, 0x01), /* CKV timing control on/off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) CMD2(0xd9, 0x00, 0x08), /* CKV 1,2 timing control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) CMD2(0xde, 0x05, 0x0a), /* OEV timing control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) CMD2(0xdf, 0x0a, 0x19), /* ASW timing control (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) CMD1(0xe0, 0x0a), /* ASW timing control (2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) CMD0(0x21), /* Invert for normally black display */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) CMD0(0x29), /* Display on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) CMD_NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static const uint32_t lcd_vga_pass_through_tdo35s[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) CMD1(0xB0, 0x16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) CMD1(0xBC, 0x80),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) CMD1(0xE1, 0x00),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) CMD1(0x3B, 0x00),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) CMD_NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static const uint32_t lcd_qvga_pass_through_tdo35s[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) CMD1(0xB0, 0x16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) CMD1(0xBC, 0x81),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) CMD1(0xE1, 0x00),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) CMD1(0x3B, 0x22),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) CMD_NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static const uint32_t lcd_vga_transfer_tdo35s[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) CMD1(0xcf, 0x02), /* Blanking period control (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) CMD1(0xd1, 0x01), /* CKV timing control on/off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) CMD2(0xd2, 0x00, 0x1e), /* CKV 1,2 timing control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) CMD2(0xd3, 0x14, 0x28), /* OEV timing control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) CMD2(0xd4, 0x28, 0x64), /* ASW timing control (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) CMD1(0xd5, 0x28), /* ASW timing control (2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) CMD0(0x21), /* Invert for normally black display */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) CMD0(0x29), /* Display on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) CMD_NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static const uint32_t lcd_panel_config[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) CMD2(0xb8, 0xff, 0xf9), /* Output control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) CMD0(0x11), /* sleep out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) CMD1(0xba, 0x01), /* Display mode (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) CMD1(0xbb, 0x00), /* Display mode (2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) CMD1(0x3a, 0x60), /* Display mode 18-bit RGB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) CMD1(0xbf, 0x10), /* Drive system change control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) CMD1(0xb1, 0x56), /* Booster operation setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) CMD1(0xb2, 0x33), /* Booster mode setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) CMD1(0xb3, 0x11), /* Booster frequency setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) CMD1(0xb4, 0x02), /* Op amp/system clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) CMD1(0xb5, 0x35), /* VCS voltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) CMD1(0xb6, 0x40), /* VCOM voltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) CMD1(0xb7, 0x03), /* External display signal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) CMD1(0xbd, 0x00), /* ASW slew rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) CMD1(0xbe, 0x00), /* Dummy data for QuadData operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) CMD1(0xc0, 0x11), /* Sleep out FR count (A) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) CMD1(0xc1, 0x11), /* Sleep out FR count (B) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) CMD1(0xc2, 0x11), /* Sleep out FR count (C) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) CMD2(0xc3, 0x20, 0x40), /* Sleep out FR count (D) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) CMD2(0xc4, 0x60, 0xc0), /* Sleep out FR count (E) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) CMD2(0xc5, 0x10, 0x20), /* Sleep out FR count (F) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) CMD1(0xc6, 0xc0), /* Sleep out FR count (G) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) CMD2(0xc7, 0x33, 0x43), /* Gamma 1 fine tuning (1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) CMD1(0xc8, 0x44), /* Gamma 1 fine tuning (2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) CMD1(0xc9, 0x33), /* Gamma 1 inclination adjustment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) CMD1(0xca, 0x00), /* Gamma 1 blue offset adjustment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) CMD2(0xec, 0x01, 0xf0), /* Horizontal clock cycles */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) CMD_NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static int tdo24m_writes(struct tdo24m *lcd, const uint32_t *array)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct spi_transfer *x = &lcd->xfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) const uint32_t *p = array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) uint32_t data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) int nparams, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) for (; *p != CMD_NULL; p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (!lcd->color_invert && *p == CMD0(0x21))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) nparams = (*p >> 30) & 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) data = *p << (7 - nparams);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) switch (nparams) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) lcd->buf[0] = (data >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) lcd->buf[1] = data & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) lcd->buf[0] = (data >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) lcd->buf[1] = (data >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) lcd->buf[2] = data & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) lcd->buf[0] = (data >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) lcd->buf[1] = (data >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) lcd->buf[2] = (data >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) lcd->buf[3] = data & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) x->len = nparams + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) err = spi_sync(lcd->spi_dev, &lcd->msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static int tdo24m_adj_mode(struct tdo24m *lcd, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) case MODE_VGA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) tdo24m_writes(lcd, lcd_vga_pass_through_tdo24m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) tdo24m_writes(lcd, lcd_panel_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) tdo24m_writes(lcd, lcd_vga_transfer_tdo24m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) case MODE_QVGA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) tdo24m_writes(lcd, lcd_qvga_pass_through_tdo24m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) tdo24m_writes(lcd, lcd_panel_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) tdo24m_writes(lcd, lcd_qvga_transfer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) lcd->mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static int tdo35s_adj_mode(struct tdo24m *lcd, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) case MODE_VGA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) tdo24m_writes(lcd, lcd_vga_pass_through_tdo35s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) tdo24m_writes(lcd, lcd_panel_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) tdo24m_writes(lcd, lcd_vga_transfer_tdo35s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) case MODE_QVGA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) tdo24m_writes(lcd, lcd_qvga_pass_through_tdo35s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) tdo24m_writes(lcd, lcd_panel_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) tdo24m_writes(lcd, lcd_qvga_transfer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) lcd->mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static int tdo24m_power_on(struct tdo24m *lcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) err = tdo24m_writes(lcd, lcd_panel_on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) err = tdo24m_writes(lcd, lcd_panel_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) err = lcd->adj_mode(lcd, lcd->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static int tdo24m_power_off(struct tdo24m *lcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return tdo24m_writes(lcd, lcd_panel_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static int tdo24m_power(struct tdo24m *lcd, int power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ret = tdo24m_power_on(lcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) ret = tdo24m_power_off(lcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) lcd->power = power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static int tdo24m_set_power(struct lcd_device *ld, int power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) struct tdo24m *lcd = lcd_get_data(ld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return tdo24m_power(lcd, power);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static int tdo24m_get_power(struct lcd_device *ld)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct tdo24m *lcd = lcd_get_data(ld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return lcd->power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static int tdo24m_set_mode(struct lcd_device *ld, struct fb_videomode *m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct tdo24m *lcd = lcd_get_data(ld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) int mode = MODE_QVGA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (m->xres == 640 || m->xres == 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) mode = MODE_VGA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (lcd->mode == mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return lcd->adj_mode(lcd, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static struct lcd_ops tdo24m_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) .get_power = tdo24m_get_power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) .set_power = tdo24m_set_power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) .set_mode = tdo24m_set_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static int tdo24m_probe(struct spi_device *spi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct tdo24m *lcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) struct spi_message *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) struct spi_transfer *x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct tdo24m_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) enum tdo24m_model model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) pdata = dev_get_platdata(&spi->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) model = pdata->model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) model = TDO24M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) spi->bits_per_word = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) spi->mode = SPI_MODE_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) err = spi_setup(spi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) lcd = devm_kzalloc(&spi->dev, sizeof(struct tdo24m), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (!lcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) lcd->spi_dev = spi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) lcd->power = FB_BLANK_POWERDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) lcd->mode = MODE_VGA; /* default to VGA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) lcd->buf = devm_kzalloc(&spi->dev, TDO24M_SPI_BUFF_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (lcd->buf == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) m = &lcd->msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) x = &lcd->xfer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) spi_message_init(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) x->cs_change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) x->tx_buf = &lcd->buf[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) spi_message_add_tail(x, m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) switch (model) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) case TDO24M:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) lcd->color_invert = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) lcd->adj_mode = tdo24m_adj_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) case TDO35S:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) lcd->adj_mode = tdo35s_adj_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) lcd->color_invert = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) dev_err(&spi->dev, "Unsupported model");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) lcd->lcd_dev = devm_lcd_device_register(&spi->dev, "tdo24m", &spi->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) lcd, &tdo24m_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (IS_ERR(lcd->lcd_dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return PTR_ERR(lcd->lcd_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) spi_set_drvdata(spi, lcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) err = tdo24m_power(lcd, FB_BLANK_UNBLANK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static int tdo24m_remove(struct spi_device *spi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct tdo24m *lcd = spi_get_drvdata(spi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) tdo24m_power(lcd, FB_BLANK_POWERDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static int tdo24m_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) struct tdo24m *lcd = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return tdo24m_power(lcd, FB_BLANK_POWERDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) static int tdo24m_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct tdo24m *lcd = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return tdo24m_power(lcd, FB_BLANK_UNBLANK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) static SIMPLE_DEV_PM_OPS(tdo24m_pm_ops, tdo24m_suspend, tdo24m_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /* Power down all displays on reboot, poweroff or halt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static void tdo24m_shutdown(struct spi_device *spi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct tdo24m *lcd = spi_get_drvdata(spi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) tdo24m_power(lcd, FB_BLANK_POWERDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) static struct spi_driver tdo24m_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) .name = "tdo24m",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) .pm = &tdo24m_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) .probe = tdo24m_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) .remove = tdo24m_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) .shutdown = tdo24m_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) module_spi_driver(tdo24m_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) MODULE_DESCRIPTION("Driver for Toppoly TDO24M LCD Panel");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) MODULE_ALIAS("spi:tdo24m");