^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) * S6E63M0 AMOLED LCD drm_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 Paweł Chmiel <pawel.mikolaj.chmiel@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Derived from drivers/gpu/drm/panel-samsung-ld9040.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Andrzej Hajda <a.hajda@samsung.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <drm/drm_modes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <drm/drm_panel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/backlight.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <video/mipi_display.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "panel-samsung-s6e63m0.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /* Manufacturer Command Set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define MCS_ELVSS_ON 0xb1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define MCS_MIECTL1 0xc0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define MCS_BCMODE 0xc1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define MCS_ERROR_CHECK 0xd5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define MCS_READ_ID1 0xda
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define MCS_READ_ID2 0xdb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define MCS_READ_ID3 0xdc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define MCS_LEVEL_2_KEY 0xf0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define MCS_MTP_KEY 0xf1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define MCS_DISCTL 0xf2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define MCS_SRCCTL 0xf6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define MCS_IFCTL 0xf7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define MCS_PANELCTL 0xF8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define MCS_PGAMMACTL 0xfa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define S6E63M0_LCD_ID_VALUE_M2 0xA4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define S6E63M0_LCD_ID_VALUE_SM2 0xB4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define S6E63M0_LCD_ID_VALUE_SM2_1 0xB6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define NUM_GAMMA_LEVELS 11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define GAMMA_TABLE_COUNT 23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define MAX_BRIGHTNESS (NUM_GAMMA_LEVELS - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* array of gamma tables for gamma value 2.2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static u8 const s6e63m0_gamma_22[NUM_GAMMA_LEVELS][GAMMA_TABLE_COUNT] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) { MCS_PGAMMACTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) 0x18, 0x08, 0x24, 0x78, 0xEC, 0x3D, 0xC8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) 0xC2, 0xB6, 0xC4, 0xC7, 0xB6, 0xD5, 0xD7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) 0xCC, 0x00, 0x39, 0x00, 0x36, 0x00, 0x51 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) { MCS_PGAMMACTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) 0x18, 0x08, 0x24, 0x73, 0x4A, 0x3D, 0xC0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) 0xC2, 0xB1, 0xBB, 0xBE, 0xAC, 0xCE, 0xCF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) 0xC5, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x82 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) { MCS_PGAMMACTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) 0x18, 0x08, 0x24, 0x70, 0x51, 0x3E, 0xBF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) 0xC1, 0xAF, 0xB9, 0xBC, 0xAB, 0xCC, 0xCC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) 0xC2, 0x00, 0x65, 0x00, 0x67, 0x00, 0x8D },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) { MCS_PGAMMACTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) 0x18, 0x08, 0x24, 0x6C, 0x54, 0x3A, 0xBC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) 0xBF, 0xAC, 0xB7, 0xBB, 0xA9, 0xC9, 0xC9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) 0xBE, 0x00, 0x71, 0x00, 0x73, 0x00, 0x9E },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) { MCS_PGAMMACTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) 0x18, 0x08, 0x24, 0x69, 0x54, 0x37, 0xBB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) 0xBE, 0xAC, 0xB4, 0xB7, 0xA6, 0xC7, 0xC8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) 0xBC, 0x00, 0x7B, 0x00, 0x7E, 0x00, 0xAB },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) { MCS_PGAMMACTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) 0x18, 0x08, 0x24, 0x66, 0x55, 0x34, 0xBA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) 0xBD, 0xAB, 0xB1, 0xB5, 0xA3, 0xC5, 0xC6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) 0xB9, 0x00, 0x85, 0x00, 0x88, 0x00, 0xBA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) { MCS_PGAMMACTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) 0x18, 0x08, 0x24, 0x63, 0x53, 0x31, 0xB8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) 0xBC, 0xA9, 0xB0, 0xB5, 0xA2, 0xC4, 0xC4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) 0xB8, 0x00, 0x8B, 0x00, 0x8E, 0x00, 0xC2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) { MCS_PGAMMACTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) 0x18, 0x08, 0x24, 0x62, 0x54, 0x30, 0xB9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) 0xBB, 0xA9, 0xB0, 0xB3, 0xA1, 0xC1, 0xC3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) 0xB7, 0x00, 0x91, 0x00, 0x95, 0x00, 0xDA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) { MCS_PGAMMACTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) 0x18, 0x08, 0x24, 0x66, 0x58, 0x34, 0xB6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) 0xBA, 0xA7, 0xAF, 0xB3, 0xA0, 0xC1, 0xC2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) 0xB7, 0x00, 0x97, 0x00, 0x9A, 0x00, 0xD1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) { MCS_PGAMMACTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) 0x18, 0x08, 0x24, 0x64, 0x56, 0x33, 0xB6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) 0xBA, 0xA8, 0xAC, 0xB1, 0x9D, 0xC1, 0xC1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) 0xB7, 0x00, 0x9C, 0x00, 0x9F, 0x00, 0xD6 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) { MCS_PGAMMACTL, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) 0x18, 0x08, 0x24, 0x5f, 0x50, 0x2d, 0xB6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) 0xB9, 0xA7, 0xAd, 0xB1, 0x9f, 0xbe, 0xC0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) 0xB5, 0x00, 0xa0, 0x00, 0xa4, 0x00, 0xdb },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct s6e63m0 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int (*dcs_read)(struct device *dev, const u8 cmd, u8 *val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int (*dcs_write)(struct device *dev, const u8 *data, size_t len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct drm_panel panel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct backlight_device *bl_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) u8 lcd_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct regulator_bulk_data supplies[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct gpio_desc *reset_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) bool prepared;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) bool enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * This field is tested by functions directly accessing bus before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * transfer, transfer is skipped if it is set. In case of transfer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * failure or unexpected response the field is set to error value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * Such construct allows to eliminate many checks in higher level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static const struct drm_display_mode default_mode = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .clock = 25628,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .hdisplay = 480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .hsync_start = 480 + 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .hsync_end = 480 + 16 + 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .htotal = 480 + 16 + 2 + 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .vdisplay = 800,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .vsync_start = 800 + 28,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .vsync_end = 800 + 28 + 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .vtotal = 800 + 28 + 2 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .width_mm = 53,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .height_mm = 89,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static inline struct s6e63m0 *panel_to_s6e63m0(struct drm_panel *panel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return container_of(panel, struct s6e63m0, panel);
^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) static int s6e63m0_clear_error(struct s6e63m0 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int ret = ctx->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) ctx->error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return ret;
^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 s6e63m0_dcs_read(struct s6e63m0 *ctx, const u8 cmd, u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (ctx->error < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) ctx->error = ctx->dcs_read(ctx->dev, cmd, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static void s6e63m0_dcs_write(struct s6e63m0 *ctx, const u8 *data, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (ctx->error < 0 || len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ctx->error = ctx->dcs_write(ctx->dev, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #define s6e63m0_dcs_write_seq_static(ctx, seq ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static const u8 d[] = { seq }; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) s6e63m0_dcs_write(ctx, d, ARRAY_SIZE(d)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static int s6e63m0_check_lcd_type(struct s6e63m0 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) u8 id1, id2, id3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) s6e63m0_dcs_read(ctx, MCS_READ_ID1, &id1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) s6e63m0_dcs_read(ctx, MCS_READ_ID2, &id2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) s6e63m0_dcs_read(ctx, MCS_READ_ID3, &id3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ret = s6e63m0_clear_error(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) dev_err(ctx->dev, "error checking LCD type (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) ctx->lcd_type = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) dev_info(ctx->dev, "MTP ID: %02x %02x %02x\n", id1, id2, id3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /* We attempt to detect what panel is mounted on the controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) switch (id2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) case S6E63M0_LCD_ID_VALUE_M2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) dev_info(ctx->dev, "detected LCD panel AMS397GE MIPI M2\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) case S6E63M0_LCD_ID_VALUE_SM2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) case S6E63M0_LCD_ID_VALUE_SM2_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) dev_info(ctx->dev, "detected LCD panel AMS397GE MIPI SM2\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) dev_info(ctx->dev, "unknown LCD panel type %02x\n", id2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) ctx->lcd_type = id2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static void s6e63m0_init(struct s6e63m0 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) s6e63m0_dcs_write_seq_static(ctx, MCS_PANELCTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 0x01, 0x27, 0x27, 0x07, 0x07, 0x54, 0x9f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 0x63, 0x86, 0x1a, 0x33, 0x0d, 0x00, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) s6e63m0_dcs_write_seq_static(ctx, MCS_DISCTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 0x02, 0x03, 0x1c, 0x10, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) s6e63m0_dcs_write_seq_static(ctx, MCS_IFCTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 0x03, 0x00, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) s6e63m0_dcs_write_seq_static(ctx, MCS_PGAMMACTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 0x00, 0x18, 0x08, 0x24, 0x64, 0x56, 0x33,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 0xb6, 0xba, 0xa8, 0xac, 0xb1, 0x9d, 0xc1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 0xc1, 0xb7, 0x00, 0x9c, 0x00, 0x9f, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 0xd6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) s6e63m0_dcs_write_seq_static(ctx, MCS_PGAMMACTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) s6e63m0_dcs_write_seq_static(ctx, MCS_SRCCTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 0x00, 0x8c, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) s6e63m0_dcs_write_seq_static(ctx, 0xb3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 0xc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) s6e63m0_dcs_write_seq_static(ctx, 0xb5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 0x2c, 0x12, 0x0c, 0x0a, 0x10, 0x0e, 0x17,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 0x13, 0x1f, 0x1a, 0x2a, 0x24, 0x1f, 0x1b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 0x1a, 0x17, 0x2b, 0x26, 0x22, 0x20, 0x3a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 0x34, 0x30, 0x2c, 0x29, 0x26, 0x25, 0x23,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 0x21, 0x20, 0x1e, 0x1e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) s6e63m0_dcs_write_seq_static(ctx, 0xb6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x44,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 0x44, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 0x66, 0x66);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) s6e63m0_dcs_write_seq_static(ctx, 0xb7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 0x2c, 0x12, 0x0c, 0x0a, 0x10, 0x0e, 0x17,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 0x13, 0x1f, 0x1a, 0x2a, 0x24, 0x1f, 0x1b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 0x1a, 0x17, 0x2b, 0x26, 0x22, 0x20, 0x3a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 0x34, 0x30, 0x2c, 0x29, 0x26, 0x25, 0x23,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 0x21, 0x20, 0x1e, 0x1e, 0x00, 0x00, 0x11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 0x22, 0x33, 0x44, 0x44, 0x44, 0x55, 0x55,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 0x66, 0x66, 0x66, 0x66, 0x66, 0x66);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) s6e63m0_dcs_write_seq_static(ctx, 0xb9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 0x2c, 0x12, 0x0c, 0x0a, 0x10, 0x0e, 0x17,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 0x13, 0x1f, 0x1a, 0x2a, 0x24, 0x1f, 0x1b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 0x1a, 0x17, 0x2b, 0x26, 0x22, 0x20, 0x3a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 0x34, 0x30, 0x2c, 0x29, 0x26, 0x25, 0x23,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 0x21, 0x20, 0x1e, 0x1e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) s6e63m0_dcs_write_seq_static(ctx, 0xba,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x44,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 0x44, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 0x66, 0x66);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) s6e63m0_dcs_write_seq_static(ctx, MCS_BCMODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 0x4d, 0x96, 0x1d, 0x00, 0x00, 0x01, 0xdf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 0x00, 0x00, 0x03, 0x1f, 0x00, 0x00, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 0x09, 0x0d, 0x0f, 0x12, 0x15, 0x18);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) s6e63m0_dcs_write_seq_static(ctx, 0xb2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 0x10, 0x10, 0x0b, 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) s6e63m0_dcs_write_seq_static(ctx, MCS_MIECTL1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) s6e63m0_dcs_write_seq_static(ctx, MCS_ELVSS_ON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 0x0b);
^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 s6e63m0_power_on(struct s6e63m0 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) msleep(25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* Be sure to send a reset pulse */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) gpiod_set_value(ctx->reset_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) msleep(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) gpiod_set_value(ctx->reset_gpio, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) msleep(120);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static int s6e63m0_power_off(struct s6e63m0 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) gpiod_set_value(ctx->reset_gpio, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) msleep(120);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return ret;
^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 s6e63m0_disable(struct drm_panel *panel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct s6e63m0 *ctx = panel_to_s6e63m0(panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (!ctx->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) backlight_disable(ctx->bl_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) s6e63m0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) s6e63m0_dcs_write_seq_static(ctx, MIPI_DCS_ENTER_SLEEP_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) msleep(120);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) ctx->enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static int s6e63m0_unprepare(struct drm_panel *panel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) struct s6e63m0 *ctx = panel_to_s6e63m0(panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (!ctx->prepared)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) s6e63m0_clear_error(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) ret = s6e63m0_power_off(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) ctx->prepared = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) static int s6e63m0_prepare(struct drm_panel *panel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) struct s6e63m0 *ctx = panel_to_s6e63m0(panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (ctx->prepared)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) ret = s6e63m0_power_on(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) /* Magic to unlock level 2 control of the display */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) s6e63m0_dcs_write_seq_static(ctx, MCS_LEVEL_2_KEY, 0x5a, 0x5a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* Magic to unlock MTP reading */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) s6e63m0_dcs_write_seq_static(ctx, MCS_MTP_KEY, 0x5a, 0x5a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) ret = s6e63m0_check_lcd_type(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) s6e63m0_init(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) ret = s6e63m0_clear_error(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) s6e63m0_unprepare(panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) ctx->prepared = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static int s6e63m0_enable(struct drm_panel *panel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) struct s6e63m0 *ctx = panel_to_s6e63m0(panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (ctx->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) s6e63m0_dcs_write_seq_static(ctx, MIPI_DCS_EXIT_SLEEP_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) msleep(120);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) s6e63m0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) s6e63m0_dcs_write_seq_static(ctx, MCS_ERROR_CHECK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 0xE7, 0x14, 0x60, 0x17, 0x0A, 0x49, 0xC3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 0x8F, 0x19, 0x64, 0x91, 0x84, 0x76, 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 0x0F, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) backlight_enable(ctx->bl_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) ctx->enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static int s6e63m0_get_modes(struct drm_panel *panel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) struct drm_connector *connector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct drm_display_mode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) mode = drm_mode_duplicate(connector->dev, &default_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (!mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) default_mode.hdisplay, default_mode.vdisplay,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) drm_mode_vrefresh(&default_mode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return -ENOMEM;
^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) drm_mode_set_name(mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) drm_mode_probed_add(connector, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return 1;
^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 const struct drm_panel_funcs s6e63m0_drm_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) .disable = s6e63m0_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) .unprepare = s6e63m0_unprepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) .prepare = s6e63m0_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) .enable = s6e63m0_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) .get_modes = s6e63m0_get_modes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) static int s6e63m0_set_brightness(struct backlight_device *bd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) struct s6e63m0 *ctx = bl_get_data(bd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) int brightness = bd->props.brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /* disable and set new gamma */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) s6e63m0_dcs_write(ctx, s6e63m0_gamma_22[brightness],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) ARRAY_SIZE(s6e63m0_gamma_22[brightness]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /* update gamma table. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) s6e63m0_dcs_write_seq_static(ctx, MCS_PGAMMACTL, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) return s6e63m0_clear_error(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) static const struct backlight_ops s6e63m0_backlight_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) .update_status = s6e63m0_set_brightness,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) static int s6e63m0_backlight_register(struct s6e63m0 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) struct backlight_properties props = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) .type = BACKLIGHT_RAW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) .brightness = MAX_BRIGHTNESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) .max_brightness = MAX_BRIGHTNESS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) struct device *dev = ctx->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) ctx->bl_dev = devm_backlight_device_register(dev, "panel", dev, ctx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) &s6e63m0_backlight_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) &props);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (IS_ERR(ctx->bl_dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) ret = PTR_ERR(ctx->bl_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) dev_err(dev, "error registering backlight device (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) int s6e63m0_probe(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) int (*dcs_read)(struct device *dev, const u8 cmd, u8 *val),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) int (*dcs_write)(struct device *dev, const u8 *data, size_t len),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) bool dsi_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct s6e63m0 *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ctx = devm_kzalloc(dev, sizeof(struct s6e63m0), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (!ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) ctx->dcs_read = dcs_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) ctx->dcs_write = dcs_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) dev_set_drvdata(dev, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) ctx->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) ctx->enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) ctx->prepared = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) ctx->supplies[0].supply = "vdd3";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) ctx->supplies[1].supply = "vci";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) ctx->supplies);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) dev_err(dev, "failed to get regulators: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (IS_ERR(ctx->reset_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) dev_err(dev, "cannot get reset-gpios %ld\n", PTR_ERR(ctx->reset_gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) return PTR_ERR(ctx->reset_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) drm_panel_init(&ctx->panel, dev, &s6e63m0_drm_funcs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) dsi_mode ? DRM_MODE_CONNECTOR_DSI :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) DRM_MODE_CONNECTOR_DPI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) ret = s6e63m0_backlight_register(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) drm_panel_add(&ctx->panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) EXPORT_SYMBOL_GPL(s6e63m0_probe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) int s6e63m0_remove(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct s6e63m0 *ctx = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) drm_panel_remove(&ctx->panel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) EXPORT_SYMBOL_GPL(s6e63m0_remove);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) MODULE_AUTHOR("Paweł Chmiel <pawel.mikolaj.chmiel@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) MODULE_DESCRIPTION("s6e63m0 LCD Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) MODULE_LICENSE("GPL v2");