1ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda/* 2ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda * ld9040 AMOLED LCD drm_panel driver. 3ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda * 4ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda * Copyright (c) 2014 Samsung Electronics Co., Ltd 5ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda * Derived from drivers/video/backlight/ld9040.c 6ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda * 7ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda * Andrzej Hajda <a.hajda@samsung.com> 8ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda * 9ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda * This program is free software; you can redistribute it and/or modify 10ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda * it under the terms of the GNU General Public License version 2 as 11ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda * published by the Free Software Foundation. 12ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda*/ 13ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 14ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda#include <drm/drmP.h> 15ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda#include <drm/drm_panel.h> 16ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 17ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda#include <linux/gpio/consumer.h> 18ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda#include <linux/regulator/consumer.h> 19ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda#include <linux/spi/spi.h> 20ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 21ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda#include <video/mipi_display.h> 22ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda#include <video/of_videomode.h> 23ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda#include <video/videomode.h> 24ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 25ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda/* Manufacturer Command Set */ 26ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda#define MCS_MANPWR 0xb0 27ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda#define MCS_ELVSS_ON 0xb1 28ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda#define MCS_USER_SETTING 0xf0 29ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda#define MCS_DISPCTL 0xf2 30dbd751eed83614b7300a0331ae3ab2e70cc1e73cAndrzej Hajda#define MCS_POWER_CTRL 0xf4 31ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda#define MCS_GTCON 0xf7 32ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda#define MCS_PANEL_CONDITION 0xf8 33ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda#define MCS_GAMMA_SET1 0xf9 34ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda#define MCS_GAMMA_CTRL 0xfb 35ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 36ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda/* array of gamma tables for gamma value 2.2 */ 37ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdastatic u8 const ld9040_gammas[25][22] = { 38ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0x13, 0xb2, 0xba, 0xd2, 0x00, 0x30, 0x00, 0xaf, 0xc0, 39ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xb8, 0xcd, 0x00, 0x3d, 0x00, 0xa8, 0xb8, 0xb7, 0xcd, 0x00, 0x44 }, 40ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0x13, 0xb9, 0xb9, 0xd0, 0x00, 0x3c, 0x00, 0xaf, 0xbf, 41ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xb6, 0xcb, 0x00, 0x4b, 0x00, 0xa8, 0xb9, 0xb5, 0xcc, 0x00, 0x52 }, 42ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0x13, 0xba, 0xb9, 0xcd, 0x00, 0x41, 0x00, 0xb0, 0xbe, 43ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xb5, 0xc9, 0x00, 0x51, 0x00, 0xa9, 0xb9, 0xb5, 0xca, 0x00, 0x57 }, 44ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0x13, 0xb9, 0xb8, 0xcd, 0x00, 0x46, 0x00, 0xb1, 0xbc, 45ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xb5, 0xc8, 0x00, 0x56, 0x00, 0xaa, 0xb8, 0xb4, 0xc9, 0x00, 0x5d }, 46ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0x13, 0xba, 0xb8, 0xcb, 0x00, 0x4b, 0x00, 0xb3, 0xbc, 47ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xb4, 0xc7, 0x00, 0x5c, 0x00, 0xac, 0xb8, 0xb4, 0xc8, 0x00, 0x62 }, 48ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0x13, 0xbb, 0xb7, 0xca, 0x00, 0x4f, 0x00, 0xb4, 0xbb, 49ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xb3, 0xc7, 0x00, 0x60, 0x00, 0xad, 0xb8, 0xb4, 0xc7, 0x00, 0x67 }, 50ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0x47, 0xba, 0xb6, 0xca, 0x00, 0x53, 0x00, 0xb5, 0xbb, 51ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xb3, 0xc6, 0x00, 0x65, 0x00, 0xae, 0xb8, 0xb3, 0xc7, 0x00, 0x6c }, 52ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0x71, 0xbb, 0xb5, 0xc8, 0x00, 0x57, 0x00, 0xb5, 0xbb, 53ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xb0, 0xc5, 0x00, 0x6a, 0x00, 0xae, 0xb9, 0xb1, 0xc6, 0x00, 0x70 }, 54ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0x7b, 0xbb, 0xb4, 0xc8, 0x00, 0x5b, 0x00, 0xb5, 0xba, 55ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xb1, 0xc4, 0x00, 0x6e, 0x00, 0xae, 0xb9, 0xb0, 0xc5, 0x00, 0x75 }, 56ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0x82, 0xba, 0xb4, 0xc7, 0x00, 0x5f, 0x00, 0xb5, 0xba, 57ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xb0, 0xc3, 0x00, 0x72, 0x00, 0xae, 0xb8, 0xb0, 0xc3, 0x00, 0x7a }, 58ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0x89, 0xba, 0xb3, 0xc8, 0x00, 0x62, 0x00, 0xb6, 0xba, 59ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xaf, 0xc3, 0x00, 0x76, 0x00, 0xaf, 0xb7, 0xae, 0xc4, 0x00, 0x7e }, 60ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0x8b, 0xb9, 0xb3, 0xc7, 0x00, 0x65, 0x00, 0xb7, 0xb8, 61ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xaf, 0xc3, 0x00, 0x7a, 0x00, 0x80, 0xb6, 0xae, 0xc4, 0x00, 0x81 }, 62ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0x93, 0xba, 0xb3, 0xc5, 0x00, 0x69, 0x00, 0xb8, 0xb9, 63ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xae, 0xc1, 0x00, 0x7f, 0x00, 0xb0, 0xb6, 0xae, 0xc3, 0x00, 0x85 }, 64ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0x97, 0xba, 0xb2, 0xc5, 0x00, 0x6c, 0x00, 0xb8, 0xb8, 65ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xae, 0xc1, 0x00, 0x82, 0x00, 0xb0, 0xb6, 0xae, 0xc2, 0x00, 0x89 }, 66ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0x9a, 0xba, 0xb1, 0xc4, 0x00, 0x6f, 0x00, 0xb8, 0xb8, 67ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xad, 0xc0, 0x00, 0x86, 0x00, 0xb0, 0xb7, 0xad, 0xc0, 0x00, 0x8d }, 68ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0x9c, 0xb9, 0xb0, 0xc4, 0x00, 0x72, 0x00, 0xb8, 0xb8, 69ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xac, 0xbf, 0x00, 0x8a, 0x00, 0xb0, 0xb6, 0xac, 0xc0, 0x00, 0x91 }, 70ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0x9e, 0xba, 0xb0, 0xc2, 0x00, 0x75, 0x00, 0xb9, 0xb8, 71ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xab, 0xbe, 0x00, 0x8e, 0x00, 0xb0, 0xb6, 0xac, 0xbf, 0x00, 0x94 }, 72ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0xa0, 0xb9, 0xaf, 0xc3, 0x00, 0x77, 0x00, 0xb9, 0xb7, 73ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xab, 0xbe, 0x00, 0x90, 0x00, 0xb0, 0xb6, 0xab, 0xbf, 0x00, 0x97 }, 74ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0xa2, 0xb9, 0xaf, 0xc2, 0x00, 0x7a, 0x00, 0xb9, 0xb7, 75ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xaa, 0xbd, 0x00, 0x94, 0x00, 0xb0, 0xb5, 0xab, 0xbf, 0x00, 0x9a }, 76ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0xa4, 0xb9, 0xaf, 0xc1, 0x00, 0x7d, 0x00, 0xb9, 0xb6, 77ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xaa, 0xbb, 0x00, 0x97, 0x00, 0xb1, 0xb5, 0xaa, 0xbf, 0x00, 0x9d }, 78ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0xa4, 0xb8, 0xb0, 0xbf, 0x00, 0x80, 0x00, 0xb8, 0xb6, 79ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xaa, 0xbc, 0x00, 0x9a, 0x00, 0xb0, 0xb5, 0xab, 0xbd, 0x00, 0xa0 }, 80ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0xa8, 0xb8, 0xae, 0xbe, 0x00, 0x84, 0x00, 0xb9, 0xb7, 81ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xa8, 0xbc, 0x00, 0x9d, 0x00, 0xb2, 0xb5, 0xaa, 0xbc, 0x00, 0xa4 }, 82ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0xa9, 0xb6, 0xad, 0xbf, 0x00, 0x86, 0x00, 0xb8, 0xb5, 83ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xa8, 0xbc, 0x00, 0xa0, 0x00, 0xb3, 0xb3, 0xa9, 0xbc, 0x00, 0xa7 }, 84ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0xa9, 0xb7, 0xae, 0xbd, 0x00, 0x89, 0x00, 0xb7, 0xb6, 85ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xa8, 0xba, 0x00, 0xa4, 0x00, 0xb1, 0xb4, 0xaa, 0xbb, 0x00, 0xaa }, 86ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { 0xf9, 0x00, 0xa7, 0xb4, 0xae, 0xbf, 0x00, 0x91, 0x00, 0xb2, 0xb4, 87ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0xaa, 0xbb, 0x00, 0xac, 0x00, 0xb3, 0xb1, 0xaa, 0xbc, 0x00, 0xb3 }, 88ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda}; 89ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 90ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdastruct ld9040 { 91ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct device *dev; 92ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct drm_panel panel; 93ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 94ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct regulator_bulk_data supplies[2]; 95ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct gpio_desc *reset_gpio; 96ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda u32 power_on_delay; 97ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda u32 reset_delay; 98ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct videomode vm; 99ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda u32 width_mm; 100ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda u32 height_mm; 101ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 102ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda int brightness; 103ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 104ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda /* This field is tested by functions directly accessing bus before 105ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda * transfer, transfer is skipped if it is set. In case of transfer 106ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda * failure or unexpected response the field is set to error value. 107ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda * Such construct allows to eliminate many checks in higher level 108ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda * functions. 109ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda */ 110ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda int error; 111ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda}; 112ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 113dff2ed275454b5a69b785949be73e2dcbb686e3fThierry Redingstatic inline struct ld9040 *panel_to_ld9040(struct drm_panel *panel) 114dff2ed275454b5a69b785949be73e2dcbb686e3fThierry Reding{ 115dff2ed275454b5a69b785949be73e2dcbb686e3fThierry Reding return container_of(panel, struct ld9040, panel); 116dff2ed275454b5a69b785949be73e2dcbb686e3fThierry Reding} 117ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 118ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdastatic int ld9040_clear_error(struct ld9040 *ctx) 119ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda{ 120ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda int ret = ctx->error; 121ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 122ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ctx->error = 0; 123ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return ret; 124ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda} 125ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 126ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdastatic int ld9040_spi_write_word(struct ld9040 *ctx, u16 data) 127ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda{ 128ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct spi_device *spi = to_spi_device(ctx->dev); 129ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct spi_transfer xfer = { 130ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda .len = 2, 131ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda .tx_buf = &data, 132ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda }; 133ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct spi_message msg; 134ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 135ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda spi_message_init(&msg); 136ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda spi_message_add_tail(&xfer, &msg); 137ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 138ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return spi_sync(spi, &msg); 139ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda} 140ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 141ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdastatic void ld9040_dcs_write(struct ld9040 *ctx, const u8 *data, size_t len) 142ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda{ 143ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda int ret = 0; 144ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 145ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda if (ctx->error < 0 || len == 0) 146ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return; 147ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 148ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda dev_dbg(ctx->dev, "writing dcs seq: %*ph\n", len, data); 149ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ret = ld9040_spi_write_word(ctx, *data); 150ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 151ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda while (!ret && --len) { 152ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ++data; 153ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ret = ld9040_spi_write_word(ctx, *data | 0x100); 154ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda } 155ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 156ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda if (ret) { 157ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda dev_err(ctx->dev, "error %d writing dcs seq: %*ph\n", ret, len, 158ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda data); 159ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ctx->error = ret; 160ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda } 161ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 162ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda usleep_range(300, 310); 163ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda} 164ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 165ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda#define ld9040_dcs_write_seq_static(ctx, seq...) \ 166ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda({\ 167ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda static const u8 d[] = { seq };\ 168ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ld9040_dcs_write(ctx, d, ARRAY_SIZE(d));\ 169ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda}) 170ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 171ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdastatic void ld9040_brightness_set(struct ld9040 *ctx) 172ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda{ 173ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ld9040_dcs_write(ctx, ld9040_gammas[ctx->brightness], 174ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ARRAY_SIZE(ld9040_gammas[ctx->brightness])); 175ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 176ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ld9040_dcs_write_seq_static(ctx, MCS_GAMMA_CTRL, 0x02, 0x5a); 177ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda} 178ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 179ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdastatic void ld9040_init(struct ld9040 *ctx) 180ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda{ 181ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ld9040_dcs_write_seq_static(ctx, MCS_USER_SETTING, 0x5a, 0x5a); 182ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ld9040_dcs_write_seq_static(ctx, MCS_PANEL_CONDITION, 183ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0x05, 0x65, 0x96, 0x71, 0x7d, 0x19, 0x3b, 0x0d, 184ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0x19, 0x7e, 0x0d, 0xe2, 0x00, 0x00, 0x7e, 0x7d, 185ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0x07, 0x07, 0x20, 0x20, 0x20, 0x02, 0x02); 186ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ld9040_dcs_write_seq_static(ctx, MCS_DISPCTL, 187ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 0x02, 0x08, 0x08, 0x10, 0x10); 188ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ld9040_dcs_write_seq_static(ctx, MCS_MANPWR, 0x04); 189dbd751eed83614b7300a0331ae3ab2e70cc1e73cAndrzej Hajda ld9040_dcs_write_seq_static(ctx, MCS_POWER_CTRL, 190dbd751eed83614b7300a0331ae3ab2e70cc1e73cAndrzej Hajda 0x0a, 0x87, 0x25, 0x6a, 0x44, 0x02, 0x88); 191ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ld9040_dcs_write_seq_static(ctx, MCS_ELVSS_ON, 0x0d, 0x00, 0x16); 192ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ld9040_dcs_write_seq_static(ctx, MCS_GTCON, 0x09, 0x00, 0x00); 193ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ld9040_brightness_set(ctx); 194ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ld9040_dcs_write_seq_static(ctx, MIPI_DCS_EXIT_SLEEP_MODE); 195ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ld9040_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_ON); 196ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda} 197ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 198ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdastatic int ld9040_power_on(struct ld9040 *ctx) 199ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda{ 200ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda int ret; 201ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 202ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 203ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda if (ret < 0) 204ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return ret; 205ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 206ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda msleep(ctx->power_on_delay); 207ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda gpiod_set_value(ctx->reset_gpio, 0); 208ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda msleep(ctx->reset_delay); 209ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda gpiod_set_value(ctx->reset_gpio, 1); 210ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda msleep(ctx->reset_delay); 211ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 212ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return 0; 213ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda} 214ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 215ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdastatic int ld9040_power_off(struct ld9040 *ctx) 216ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda{ 217ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 218ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda} 219ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 220ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdastatic int ld9040_disable(struct drm_panel *panel) 221ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda{ 2228141028278c2eac32a70d2c5a5178c84a4d0963eAjay Kumar return 0; 2238141028278c2eac32a70d2c5a5178c84a4d0963eAjay Kumar} 2248141028278c2eac32a70d2c5a5178c84a4d0963eAjay Kumar 2258141028278c2eac32a70d2c5a5178c84a4d0963eAjay Kumarstatic int ld9040_unprepare(struct drm_panel *panel) 2268141028278c2eac32a70d2c5a5178c84a4d0963eAjay Kumar{ 227ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct ld9040 *ctx = panel_to_ld9040(panel); 228ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 229ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda msleep(120); 230ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ld9040_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_OFF); 231ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ld9040_dcs_write_seq_static(ctx, MIPI_DCS_ENTER_SLEEP_MODE); 232ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda msleep(40); 233ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 234ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ld9040_clear_error(ctx); 235ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 236ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return ld9040_power_off(ctx); 237ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda} 238ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 239099b3e8699322efb7229913d2c1651588205f182Ajay Kumarstatic int ld9040_prepare(struct drm_panel *panel) 240099b3e8699322efb7229913d2c1651588205f182Ajay Kumar{ 241ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct ld9040 *ctx = panel_to_ld9040(panel); 242ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda int ret; 243ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 244ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ret = ld9040_power_on(ctx); 245ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda if (ret < 0) 246ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return ret; 247ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 248ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ld9040_init(ctx); 249ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 250ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ret = ld9040_clear_error(ctx); 251ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 252ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda if (ret < 0) 2538141028278c2eac32a70d2c5a5178c84a4d0963eAjay Kumar ld9040_unprepare(panel); 254ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 255ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return ret; 256ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda} 257ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 2588141028278c2eac32a70d2c5a5178c84a4d0963eAjay Kumarstatic int ld9040_enable(struct drm_panel *panel) 2598141028278c2eac32a70d2c5a5178c84a4d0963eAjay Kumar{ 2608141028278c2eac32a70d2c5a5178c84a4d0963eAjay Kumar return 0; 2618141028278c2eac32a70d2c5a5178c84a4d0963eAjay Kumar} 2628141028278c2eac32a70d2c5a5178c84a4d0963eAjay Kumar 263ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdastatic int ld9040_get_modes(struct drm_panel *panel) 264ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda{ 265ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct drm_connector *connector = panel->connector; 266ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct ld9040 *ctx = panel_to_ld9040(panel); 267ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct drm_display_mode *mode; 268ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 269ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda mode = drm_mode_create(connector->dev); 270ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda if (!mode) { 271ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda DRM_ERROR("failed to create a new display mode\n"); 272ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return 0; 273ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda } 274ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 275ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda drm_display_mode_from_videomode(&ctx->vm, mode); 276ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda mode->width_mm = ctx->width_mm; 277ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda mode->height_mm = ctx->height_mm; 278ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda connector->display_info.width_mm = mode->width_mm; 279ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda connector->display_info.height_mm = mode->height_mm; 280ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 281ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 282ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda drm_mode_probed_add(connector, mode); 283ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 284ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return 1; 285ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda} 286ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 287ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdastatic const struct drm_panel_funcs ld9040_drm_funcs = { 288ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda .disable = ld9040_disable, 289099b3e8699322efb7229913d2c1651588205f182Ajay Kumar .unprepare = ld9040_unprepare, 290099b3e8699322efb7229913d2c1651588205f182Ajay Kumar .prepare = ld9040_prepare, 291ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda .enable = ld9040_enable, 292ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda .get_modes = ld9040_get_modes, 293ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda}; 294ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 295ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdastatic int ld9040_parse_dt(struct ld9040 *ctx) 296ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda{ 297ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct device *dev = ctx->dev; 298ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct device_node *np = dev->of_node; 299ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda int ret; 300ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 301ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ret = of_get_videomode(np, &ctx->vm, 0); 302ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda if (ret < 0) 303ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return ret; 304ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 305ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda of_property_read_u32(np, "power-on-delay", &ctx->power_on_delay); 306ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda of_property_read_u32(np, "reset-delay", &ctx->reset_delay); 307ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda of_property_read_u32(np, "panel-width-mm", &ctx->width_mm); 308ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda of_property_read_u32(np, "panel-height-mm", &ctx->height_mm); 309ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 310ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return 0; 311ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda} 312ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 313ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdastatic int ld9040_probe(struct spi_device *spi) 314ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda{ 315ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct device *dev = &spi->dev; 316ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct ld9040 *ctx; 317ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda int ret; 318ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 319ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ctx = devm_kzalloc(dev, sizeof(struct ld9040), GFP_KERNEL); 320ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda if (!ctx) 321ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return -ENOMEM; 322ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 323ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda spi_set_drvdata(spi, ctx); 324ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 325ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ctx->dev = dev; 326ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ctx->brightness = ARRAY_SIZE(ld9040_gammas) - 1; 327ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 328ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ret = ld9040_parse_dt(ctx); 329ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda if (ret < 0) 330ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return ret; 331ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 332ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ctx->supplies[0].supply = "vdd3"; 333ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ctx->supplies[1].supply = "vci"; 334ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), 335ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ctx->supplies); 336ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda if (ret < 0) 337ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return ret; 338ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 339ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ctx->reset_gpio = devm_gpiod_get(dev, "reset"); 340ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda if (IS_ERR(ctx->reset_gpio)) { 341ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda dev_err(dev, "cannot get reset-gpios %ld\n", 342ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda PTR_ERR(ctx->reset_gpio)); 343ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return PTR_ERR(ctx->reset_gpio); 344ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda } 345ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ret = gpiod_direction_output(ctx->reset_gpio, 1); 346ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda if (ret < 0) { 347ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda dev_err(dev, "cannot configure reset-gpios %d\n", ret); 348ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return ret; 349ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda } 350ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 351ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda spi->bits_per_word = 9; 352ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ret = spi_setup(spi); 353ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda if (ret < 0) { 354ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda dev_err(dev, "spi setup failed.\n"); 355ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return ret; 356ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda } 357ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 358ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda drm_panel_init(&ctx->panel); 359ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ctx->panel.dev = dev; 360ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ctx->panel.funcs = &ld9040_drm_funcs; 361ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 362ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return drm_panel_add(&ctx->panel); 363ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda} 364ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 365ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdastatic int ld9040_remove(struct spi_device *spi) 366ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda{ 367ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda struct ld9040 *ctx = spi_get_drvdata(spi); 368ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 369ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda ld9040_power_off(ctx); 370ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda drm_panel_remove(&ctx->panel); 371ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 372ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda return 0; 373ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda} 374ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 375ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdastatic struct of_device_id ld9040_of_match[] = { 376ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { .compatible = "samsung,ld9040" }, 377ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda { } 378ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda}; 379ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej HajdaMODULE_DEVICE_TABLE(of, ld9040_of_match); 380ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 381ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdastatic struct spi_driver ld9040_driver = { 382ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda .probe = ld9040_probe, 383ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda .remove = ld9040_remove, 384ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda .driver = { 385ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda .name = "ld9040", 386ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda .owner = THIS_MODULE, 387ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda .of_match_table = ld9040_of_match, 388ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda }, 389ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda}; 390ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajdamodule_spi_driver(ld9040_driver); 391ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej Hajda 392ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej HajdaMODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>"); 393ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej HajdaMODULE_DESCRIPTION("ld9040 LCD Driver"); 394ff21993776325316cdbcb4ced888ce4cd31a8bc6Andrzej HajdaMODULE_LICENSE("GPL v2"); 395