^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Sony ACX565AKM LCD Panel driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2019 Texas Instruments Incorporated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Based on the omapdrm-specific panel-sony-acx565akm driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2010 Nokia Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Author: Imre Deak <imre.deak@nokia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * TODO (to be addressed with hardware access to test the changes):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * - Update backlight support to use backlight_update_status() etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * - Use prepare/unprepare for the basic power on/off of the backligt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/backlight.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/spi/spi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <video/mipi_display.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <drm/drm_connector.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <drm/drm_modes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <drm/drm_panel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define CTRL_DISP_BRIGHTNESS_CTRL_ON BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define CTRL_DISP_BACKLIGHT_ON BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define CTRL_DISP_AUTO_BRIGHTNESS_ON BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define MIPID_CMD_WRITE_CABC 0x55
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define MIPID_CMD_READ_CABC 0x56
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define MIPID_VER_LPH8923 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define MIPID_VER_LS041Y3 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define MIPID_VER_L4F00311 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define MIPID_VER_ACX565AKM 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct acx565akm_panel {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct drm_panel panel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct spi_device *spi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct gpio_desc *reset_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct backlight_device *backlight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct mutex mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) u8 display_id[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) int model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) int revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) bool has_bc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) bool has_cabc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) bool enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned int cabc_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * Next value of jiffies when we can issue the next sleep in/out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) unsigned long hw_guard_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) unsigned long hw_guard_wait; /* max guard time in jiffies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define to_acx565akm_device(p) container_of(p, struct acx565akm_panel, panel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static void acx565akm_transfer(struct acx565akm_panel *lcd, int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct spi_message m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct spi_transfer *x, xfer[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) spi_message_init(&m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) memset(xfer, 0, sizeof(xfer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) x = &xfer[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) cmd &= 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) x->tx_buf = &cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) x->bits_per_word = 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) x->len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (rlen > 1 && wlen == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * Between the command and the response data there is a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * dummy clock cycle. Add an extra bit after the command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * word to account for this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) x->bits_per_word = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) cmd <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) spi_message_add_tail(x, &m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (wlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) x++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) x->tx_buf = wbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) x->len = wlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) x->bits_per_word = 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) spi_message_add_tail(x, &m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (rlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) x++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) x->rx_buf = rbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) x->len = rlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) spi_message_add_tail(x, &m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ret = spi_sync(lcd->spi, &m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) dev_dbg(&lcd->spi->dev, "spi_sync %d\n", ret);
^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 inline void acx565akm_cmd(struct acx565akm_panel *lcd, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) acx565akm_transfer(lcd, cmd, NULL, 0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static inline void acx565akm_write(struct acx565akm_panel *lcd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int reg, const u8 *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) acx565akm_transfer(lcd, reg, buf, len, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static inline void acx565akm_read(struct acx565akm_panel *lcd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int reg, u8 *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) acx565akm_transfer(lcd, reg, NULL, 0, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * Auto Brightness Control Via sysfs
^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 unsigned int acx565akm_get_cabc_mode(struct acx565akm_panel *lcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return lcd->cabc_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static void acx565akm_set_cabc_mode(struct acx565akm_panel *lcd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) unsigned int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) u16 cabc_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) lcd->cabc_mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (!lcd->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) cabc_ctrl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) acx565akm_read(lcd, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) cabc_ctrl &= ~3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) cabc_ctrl |= (1 << 8) | (mode & 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) acx565akm_write(lcd, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static unsigned int acx565akm_get_hw_cabc_mode(struct acx565akm_panel *lcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) u8 cabc_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) acx565akm_read(lcd, MIPID_CMD_READ_CABC, &cabc_ctrl, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return cabc_ctrl & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static const char * const acx565akm_cabc_modes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) "off", /* always used when CABC is not supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) "ui",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) "still-image",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) "moving-image",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static ssize_t cabc_mode_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct acx565akm_panel *lcd = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) const char *mode_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) int mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (!lcd->has_cabc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) mode = acx565akm_get_cabc_mode(lcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) mode_str = "unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (mode >= 0 && mode < ARRAY_SIZE(acx565akm_cabc_modes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) mode_str = acx565akm_cabc_modes[mode];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return sprintf(buf, "%s\n", mode_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static ssize_t cabc_mode_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct acx565akm_panel *lcd = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) for (i = 0; i < ARRAY_SIZE(acx565akm_cabc_modes); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) const char *mode_str = acx565akm_cabc_modes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) int cmp_len = strlen(mode_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (count > 0 && buf[count - 1] == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (count != cmp_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (strncmp(buf, mode_str, cmp_len) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (i == ARRAY_SIZE(acx565akm_cabc_modes))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (!lcd->has_cabc && i != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) mutex_lock(&lcd->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) acx565akm_set_cabc_mode(lcd, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) mutex_unlock(&lcd->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static ssize_t cabc_available_modes_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct acx565akm_panel *lcd = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) size_t len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (!lcd->has_cabc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return sprintf(buf, "%s\n", acx565akm_cabc_modes[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) for (i = 0; i < ARRAY_SIZE(acx565akm_cabc_modes); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) len += sprintf(&buf[len], "%s%s", i ? " " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) acx565akm_cabc_modes[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) buf[len++] = '\n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static DEVICE_ATTR_RW(cabc_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static DEVICE_ATTR_RO(cabc_available_modes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static struct attribute *acx565akm_cabc_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) &dev_attr_cabc_mode.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) &dev_attr_cabc_available_modes.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static const struct attribute_group acx565akm_cabc_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .attrs = acx565akm_cabc_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * Backlight Device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static int acx565akm_get_actual_brightness(struct acx565akm_panel *lcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) u8 bv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) acx565akm_read(lcd, MIPI_DCS_GET_DISPLAY_BRIGHTNESS, &bv, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return bv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static void acx565akm_set_brightness(struct acx565akm_panel *lcd, int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) u16 ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) int bv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) bv = level | (1 << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) acx565akm_write(lcd, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, (u8 *)&bv, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) acx565akm_read(lcd, MIPI_DCS_GET_CONTROL_DISPLAY, (u8 *)&ctrl, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) CTRL_DISP_BACKLIGHT_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) CTRL_DISP_BACKLIGHT_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) ctrl |= 1 << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) acx565akm_write(lcd, MIPI_DCS_WRITE_CONTROL_DISPLAY, (u8 *)&ctrl, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) static int acx565akm_bl_update_status_locked(struct backlight_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct acx565akm_panel *lcd = dev_get_drvdata(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) int level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) dev->props.power == FB_BLANK_UNBLANK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) level = dev->props.brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) level = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) acx565akm_set_brightness(lcd, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) static int acx565akm_bl_update_status(struct backlight_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct acx565akm_panel *lcd = dev_get_drvdata(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) mutex_lock(&lcd->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) ret = acx565akm_bl_update_status_locked(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) mutex_unlock(&lcd->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static int acx565akm_bl_get_intensity(struct backlight_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct acx565akm_panel *lcd = dev_get_drvdata(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) unsigned int intensity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) mutex_lock(&lcd->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) dev->props.power == FB_BLANK_UNBLANK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) intensity = acx565akm_get_actual_brightness(lcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) intensity = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) mutex_unlock(&lcd->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return intensity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static const struct backlight_ops acx565akm_bl_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) .get_brightness = acx565akm_bl_get_intensity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) .update_status = acx565akm_bl_update_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static int acx565akm_backlight_init(struct acx565akm_panel *lcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) struct backlight_properties props = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) .fb_blank = FB_BLANK_UNBLANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) .power = FB_BLANK_UNBLANK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) .type = BACKLIGHT_RAW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) lcd->backlight = backlight_device_register(lcd->name, &lcd->spi->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) lcd, &acx565akm_bl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) &props);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (IS_ERR(lcd->backlight)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) ret = PTR_ERR(lcd->backlight);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) lcd->backlight = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (lcd->has_cabc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) ret = sysfs_create_group(&lcd->backlight->dev.kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) &acx565akm_cabc_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) dev_err(&lcd->spi->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) "%s failed to create sysfs files\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) backlight_device_unregister(lcd->backlight);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) lcd->cabc_mode = acx565akm_get_hw_cabc_mode(lcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) lcd->backlight->props.max_brightness = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) lcd->backlight->props.brightness = acx565akm_get_actual_brightness(lcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) acx565akm_bl_update_status_locked(lcd->backlight);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static void acx565akm_backlight_cleanup(struct acx565akm_panel *lcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (lcd->has_cabc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) sysfs_remove_group(&lcd->backlight->dev.kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) &acx565akm_cabc_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) backlight_device_unregister(lcd->backlight);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * DRM Bridge Operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static void acx565akm_set_sleep_mode(struct acx565akm_panel *lcd, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) int cmd = on ? MIPI_DCS_ENTER_SLEEP_MODE : MIPI_DCS_EXIT_SLEEP_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) unsigned long wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * We have to keep 120msec between sleep in/out commands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * (8.2.15, 8.2.16).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) wait = lcd->hw_guard_end - jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if ((long)wait > 0 && wait <= lcd->hw_guard_wait) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) set_current_state(TASK_UNINTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) schedule_timeout(wait);
^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) acx565akm_cmd(lcd, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) lcd->hw_guard_wait = msecs_to_jiffies(120);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) lcd->hw_guard_end = jiffies + lcd->hw_guard_wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) static void acx565akm_set_display_state(struct acx565akm_panel *lcd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) int enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) int cmd = enabled ? MIPI_DCS_SET_DISPLAY_ON : MIPI_DCS_SET_DISPLAY_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) acx565akm_cmd(lcd, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static int acx565akm_power_on(struct acx565akm_panel *lcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) /*FIXME tweak me */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) msleep(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) gpiod_set_value(lcd->reset_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (lcd->enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) dev_dbg(&lcd->spi->dev, "panel already enabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * We have to meet all the following delay requirements:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * 1. tRW: reset pulse width 10usec (7.12.1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * 2. tRT: reset cancel time 5msec (7.12.1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * 3. Providing PCLK,HS,VS signals for 2 frames = ~50msec worst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * case (7.6.2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * 4. 120msec before the sleep out command (7.12.1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) msleep(120);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) acx565akm_set_sleep_mode(lcd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) lcd->enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /* 5msec between sleep out and the next command. (8.2.16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) usleep_range(5000, 10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) acx565akm_set_display_state(lcd, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) acx565akm_set_cabc_mode(lcd, lcd->cabc_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return acx565akm_bl_update_status_locked(lcd->backlight);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) static void acx565akm_power_off(struct acx565akm_panel *lcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (!lcd->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) acx565akm_set_display_state(lcd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) acx565akm_set_sleep_mode(lcd, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) lcd->enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * We have to provide PCLK,HS,VS signals for 2 frames (worst case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * ~50msec) after sending the sleep in command and asserting the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * reset signal. We probably could assert the reset w/o the delay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * but we still delay to avoid possible artifacts. (7.6.1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) msleep(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) gpiod_set_value(lcd->reset_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) /* FIXME need to tweak this delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) static int acx565akm_disable(struct drm_panel *panel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) struct acx565akm_panel *lcd = to_acx565akm_device(panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) mutex_lock(&lcd->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) acx565akm_power_off(lcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) mutex_unlock(&lcd->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) static int acx565akm_enable(struct drm_panel *panel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) struct acx565akm_panel *lcd = to_acx565akm_device(panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) mutex_lock(&lcd->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) acx565akm_power_on(lcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) mutex_unlock(&lcd->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) static const struct drm_display_mode acx565akm_mode = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) .clock = 24000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) .hdisplay = 800,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) .hsync_start = 800 + 28,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) .hsync_end = 800 + 28 + 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) .htotal = 800 + 28 + 4 + 24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) .vdisplay = 480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) .vsync_start = 480 + 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) .vsync_end = 480 + 3 + 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) .vtotal = 480 + 3 + 3 + 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) .width_mm = 77,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) .height_mm = 46,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) static int acx565akm_get_modes(struct drm_panel *panel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) struct drm_connector *connector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) struct drm_display_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) mode = drm_mode_duplicate(connector->dev, &acx565akm_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (!mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) drm_mode_set_name(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) drm_mode_probed_add(connector, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) connector->display_info.width_mm = acx565akm_mode.width_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) connector->display_info.height_mm = acx565akm_mode.height_mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) connector->display_info.bus_flags = DRM_BUS_FLAG_DE_HIGH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) | DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) static const struct drm_panel_funcs acx565akm_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) .disable = acx565akm_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) .enable = acx565akm_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) .get_modes = acx565akm_get_modes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) /* -----------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) * Probe, Detect and Remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) static int acx565akm_detect(struct acx565akm_panel *lcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) __be32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) u32 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) * After being taken out of reset the panel needs 5ms before the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) * command can be sent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) gpiod_set_value(lcd->reset_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) usleep_range(5000, 10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) acx565akm_read(lcd, MIPI_DCS_GET_DISPLAY_STATUS, (u8 *)&value, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) status = __be32_to_cpu(value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) lcd->enabled = (status & (1 << 17)) && (status & (1 << 10));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) dev_dbg(&lcd->spi->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) "LCD panel %s by bootloader (status 0x%04x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) lcd->enabled ? "enabled" : "disabled ", status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) acx565akm_read(lcd, MIPI_DCS_GET_DISPLAY_ID, lcd->display_id, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) dev_dbg(&lcd->spi->dev, "MIPI display ID: %02x%02x%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) lcd->display_id[0], lcd->display_id[1], lcd->display_id[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) switch (lcd->display_id[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) case 0x10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) lcd->model = MIPID_VER_ACX565AKM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) lcd->name = "acx565akm";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) lcd->has_bc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) lcd->has_cabc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) case 0x29:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) lcd->model = MIPID_VER_L4F00311;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) lcd->name = "l4f00311";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) case 0x45:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) lcd->model = MIPID_VER_LPH8923;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) lcd->name = "lph8923";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) case 0x83:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) lcd->model = MIPID_VER_LS041Y3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) lcd->name = "ls041y3";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) lcd->name = "unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) dev_err(&lcd->spi->dev, "unknown display ID\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) lcd->revision = lcd->display_id[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) dev_info(&lcd->spi->dev, "%s rev %02x panel detected\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) lcd->name, lcd->revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (!lcd->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) gpiod_set_value(lcd->reset_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) static int acx565akm_probe(struct spi_device *spi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) struct acx565akm_panel *lcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) lcd = devm_kzalloc(&spi->dev, sizeof(*lcd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (!lcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) spi_set_drvdata(spi, lcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) spi->mode = SPI_MODE_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) lcd->spi = spi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) mutex_init(&lcd->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) lcd->reset_gpio = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (IS_ERR(lcd->reset_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) dev_err(&spi->dev, "failed to get reset GPIO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) return PTR_ERR(lcd->reset_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) ret = acx565akm_detect(lcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) dev_err(&spi->dev, "panel detection failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (lcd->has_bc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) ret = acx565akm_backlight_init(lcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) drm_panel_init(&lcd->panel, &lcd->spi->dev, &acx565akm_funcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) DRM_MODE_CONNECTOR_DPI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) drm_panel_add(&lcd->panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) static int acx565akm_remove(struct spi_device *spi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) struct acx565akm_panel *lcd = spi_get_drvdata(spi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) drm_panel_remove(&lcd->panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (lcd->has_bc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) acx565akm_backlight_cleanup(lcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) drm_panel_disable(&lcd->panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) drm_panel_unprepare(&lcd->panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) static const struct of_device_id acx565akm_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) { .compatible = "sony,acx565akm", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) { /* sentinel */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) MODULE_DEVICE_TABLE(of, acx565akm_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) static const struct spi_device_id acx565akm_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) { "acx565akm", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) MODULE_DEVICE_TABLE(spi, acx565akm_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) static struct spi_driver acx565akm_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) .probe = acx565akm_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) .remove = acx565akm_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) .id_table = acx565akm_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) .name = "panel-sony-acx565akm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) .of_match_table = acx565akm_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) module_spi_driver(acx565akm_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) MODULE_AUTHOR("Nokia Corporation");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) MODULE_DESCRIPTION("Sony ACX565AKM LCD Panel Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) MODULE_LICENSE("GPL");