mirror of
https://github.com/revyos/thead-kernel.git
synced 2026-06-21 09:12:26 +02:00
sync: huiwei: 5b7b9f869c27505571944db1a6bf8815878b4bba
merge 13 commits to one Add 8911edp driver fix hall seense lpm logic add some debug info to mh248 PR:gerrit-4305/4306 PR:gerrit-4307 PR:gerrit-4308: hibernate: add resume keep swap signature for fastresume PR:gerrit-4309:Solve STD problem for DPU releted clock gate not enabled PR:gerrit-4310,driver usb: optimize pm resume time, do resume in runtime_resume PR:gerrit-4317,padctrl:light: add aon pinmux backup and restore Revert "add some debug info to mh248" This reverts commit c6cbf3c7d49caba33eee014caec3da24eb9d2388. remove suspend state judge in mh248 Fix LT8911 panel str resume problem Revert "PR:gerrit-4310,driver usb: optimize pm resume time, do resume in runtime_resume" This reverts commit 690823c5528df8e7743ce3954aec6c4473500b91.
This commit is contained in:
@@ -17,23 +17,23 @@
|
||||
vcc1v8_lontium: vcc1v8-lontium {
|
||||
compatible = "regulator-fixed";
|
||||
enable-active-high;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
gpio = <&gpio3_porta 17 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&vcc1v8_lontium_pwren>;
|
||||
regulator-name = "vcc1v8_lontium_pwren";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-name = "vcc1v8-lontium";
|
||||
};
|
||||
|
||||
vcc3v3_edp: vcc3v3-edp {
|
||||
compatible = "regulator-fixed";
|
||||
enable-active-high;
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
gpio = <&gpio2_porta 18 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&vcc3v3_edp_pwren>;
|
||||
regulator-name = "vcc3v3_edp_pwren";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-name = "vcc3v3-edp";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -59,19 +59,9 @@
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_i2c3>;
|
||||
|
||||
lt8911exb@29 {
|
||||
status = "okay";
|
||||
compatible = "lontium,lt8911exb";
|
||||
lt8911i2c: lt8911i2c@29{
|
||||
compatible = "i2c,lt8911";
|
||||
reg = <0x29>;
|
||||
lt8911exb,backlight-gpio = <&gpio2_porta 20 GPIO_ACTIVE_HIGH>;
|
||||
lt8911exb,irq-gpio = <&gpio3_porta 16 GPIO_ACTIVE_LOW>;
|
||||
lt8911exb,reset-gpio = <&gpio3_porta 15 GPIO_ACTIVE_LOW>;
|
||||
lt8911exb,rst-delay-ms = <100>;
|
||||
lt8911exb,edp-lane-cnt = <2>;
|
||||
lt8911exb,mipi-lane-cnt = <4>;
|
||||
lt8911exb,edp-depth = <8>; /* 6 or 8 */
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <<8911exb_gpios>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -106,14 +96,19 @@
|
||||
|
||||
&dhost_0 {
|
||||
panel0@0 {
|
||||
compatible = "chongzhou,cz101b4001", "jadard,jd9365da-h3";
|
||||
compatible = "i2c_dsi,lt8911";
|
||||
reg = <0>;
|
||||
backlight = <&lcd0_backlight>;
|
||||
reset-gpio = <&gpio2_porta 22 GPIO_ACTIVE_LOW>; /* active low */
|
||||
lt8911,backlight-gpio = <&gpio2_porta 20 GPIO_ACTIVE_HIGH>;
|
||||
lt8911,irq-gpio = <&gpio3_porta 16 GPIO_ACTIVE_LOW>;
|
||||
lt8911,reset-gpio = <&gpio3_porta 15 GPIO_ACTIVE_LOW>;
|
||||
lt8911,rst-delay-ms = <10>;
|
||||
lt8911,edp-lane-cnt = <2>;
|
||||
lt8911,mipi-lane-cnt = <4>;
|
||||
lt8911,edp-depth = <8>; /* 6 or 8 */
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <<8911exb_gpios>;
|
||||
hsvcc-supply = <&vcc1v8_lontium>;
|
||||
vspn3v3-supply = <&vcc3v3_edp>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&dsi_reset_gpio>;
|
||||
|
||||
port {
|
||||
panel0_in: endpoint {
|
||||
|
||||
@@ -818,8 +818,13 @@ static int dwapb_gpio_resume(struct device *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(dwapb_gpio_pm_ops, dwapb_gpio_suspend,
|
||||
dwapb_gpio_resume);
|
||||
static const struct dev_pm_ops dwapb_gpio_pm_ops = {
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(dwapb_gpio_suspend, dwapb_gpio_resume)
|
||||
};
|
||||
|
||||
|
||||
//static SIMPLE_DEV_PM_OPS(dwapb_gpio_pm_ops, dwapb_gpio_suspend,
|
||||
// dwapb_gpio_resume);
|
||||
|
||||
static struct platform_driver dwapb_gpio_driver = {
|
||||
.driver = {
|
||||
|
||||
@@ -557,4 +557,13 @@ config DRM_PANEL_HX8279
|
||||
Say Y if you want to enable support for panels based on the
|
||||
HX8279 controller.
|
||||
|
||||
config DRM_PANEL_LT8911
|
||||
tristate "LT8911-based panels"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Say Y if you want to enable support for panels based on the
|
||||
lt8911 controller.
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -59,3 +59,4 @@ obj-$(CONFIG_DRM_PANEL_HX8394) += panel-himax8394.o
|
||||
obj-$(CONFIG_DRM_PANEL_JADARD_JD9365DA_H3) += panel-jadard-jd9365da-h3.o
|
||||
obj-$(CONFIG_DRM_PANEL_MINGJUN_070BI30IA2) += panel-mingjun-070bi30ia2.o
|
||||
obj-$(CONFIG_DRM_PANEL_HX8279) += panel-hx8279.o
|
||||
obj-$(CONFIG_DRM_PANEL_LT8911) += panel-lt8911.o
|
||||
|
||||
921
drivers/gpu/drm/panel/panel-lt8911.c
Normal file
921
drivers/gpu/drm/panel/panel-lt8911.c
Normal file
@@ -0,0 +1,921 @@
|
||||
#include "panel-lt8911.h"
|
||||
#include <linux/version.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#define ILI9881_PAGE(_page) DSI_DCS_WRITE(dsi, 0xff, 0x98, 0x81, _page)
|
||||
#define IILI9881_COMMAND(_cmd, _data...) DSI_DCS_WRITE(dsi, _cmd, _data)
|
||||
#define DCS_CMD_READ_ID1 0xDA
|
||||
|
||||
#define LT_8911_I2C_ADAPTER 3
|
||||
#define LT_8911_I2C_ADDR 0x45
|
||||
|
||||
static struct i2c_mipi_dsi *g_lt8911_mipi_dsi = NULL;
|
||||
|
||||
static const struct drm_display_mode lt8911_default_mode = {
|
||||
.clock = 152840,
|
||||
.hdisplay = 1920,
|
||||
.hsync_start = 1920 + 140,
|
||||
.hsync_end = 1920 + 140 + 160,
|
||||
.htotal = 1920 + 140 + 160 + 30,
|
||||
|
||||
.vdisplay = 1080,
|
||||
.vsync_start = 1080 + 18,
|
||||
.vsync_end = 1080 + 18 + 28,
|
||||
.vtotal = 1080 + 18 + 28 + 6,
|
||||
|
||||
.width_mm = 110,
|
||||
.height_mm = 62,
|
||||
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
|
||||
};
|
||||
|
||||
static const struct panel_data lt8911_panel_data = {
|
||||
.display_mode = <8911_default_mode,
|
||||
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_VIDEO_BURST,
|
||||
.format = MIPI_DSI_FMT_RGB888,
|
||||
.lanes = 4,
|
||||
};
|
||||
|
||||
enum {
|
||||
hfp = 0,
|
||||
hs,
|
||||
hbp,
|
||||
hact,
|
||||
htotal,
|
||||
vfp,
|
||||
vs,
|
||||
vbp,
|
||||
vact,
|
||||
vtotal,
|
||||
pclk_10khz
|
||||
};
|
||||
|
||||
static int mipi_timing[] = {
|
||||
140, /* hfp */
|
||||
30, /* hs */
|
||||
160, /* hbp */
|
||||
1920, /* hact */
|
||||
2250, /* htotal */
|
||||
18, /* vfp */
|
||||
6, /* vs */
|
||||
28, /* vbp */
|
||||
1080, /* vact */
|
||||
1132, /* vtotal */
|
||||
15284 /* pixel_clk / 10000 */
|
||||
};
|
||||
|
||||
static int lt8911_i2c_write(struct i2c_client *client,
|
||||
uint8_t reg, uint8_t val)
|
||||
{
|
||||
int ret = -1;
|
||||
int retries = 0;
|
||||
uint8_t buf[2] = { reg, val };
|
||||
struct i2c_msg msg = {
|
||||
.flags = !I2C_M_RD,
|
||||
.addr = client->addr,
|
||||
.len = 2,
|
||||
.buf = buf,
|
||||
};
|
||||
|
||||
while (retries < 5) {
|
||||
ret = i2c_transfer(client->adapter, &msg, 1);
|
||||
if (ret == 1)
|
||||
return 0;
|
||||
retries++;
|
||||
}
|
||||
|
||||
DBG_FUNC("%s: write addr 0x%02x error! ret = %d\n",
|
||||
__func__, reg, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lt8911_i2c_read(struct i2c_client *client, uint8_t reg)
|
||||
{
|
||||
int ret = -1;
|
||||
int retries = 0;
|
||||
uint8_t buf[2] = { reg, 0 };
|
||||
struct i2c_msg msgs[2];
|
||||
|
||||
msgs[0].flags = client->flags;
|
||||
msgs[0].addr = client->addr;
|
||||
msgs[0].len = 1;
|
||||
msgs[0].buf = &buf[0];
|
||||
|
||||
msgs[1].flags = client->flags | I2C_M_RD;
|
||||
msgs[1].addr = client->addr;
|
||||
msgs[1].len = 1;
|
||||
msgs[1].buf = &buf[1];
|
||||
|
||||
while (retries < 5) {
|
||||
ret = i2c_transfer(client->adapter, msgs, 2);
|
||||
if (ret == 2)
|
||||
return buf[1];
|
||||
retries++;
|
||||
}
|
||||
|
||||
DBG_FUNC("%s: read addr 0x%02x error! ret = %d\n",
|
||||
__func__, reg, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lt8911_reset(struct i2c_mipi_dsi *md)
|
||||
{
|
||||
gpio_set_value(md->reset_pin, 0);
|
||||
msleep(md->rst_delay_ms);
|
||||
gpio_set_value(md->reset_pin, 1);
|
||||
msleep(md->rst_delay_ms);
|
||||
}
|
||||
|
||||
static void lt8911exb_cfg_set_mipi_timing(struct i2c_mipi_dsi *md)
|
||||
{
|
||||
struct i2c_client *client = md->client;
|
||||
|
||||
/* lt8911exb MIPI video timing configuration */
|
||||
lt8911_i2c_write(client, 0xff, 0xd0);
|
||||
lt8911_i2c_write(client, 0x0d, (u8)(mipi_timing[vtotal] / 256));
|
||||
lt8911_i2c_write(client, 0x0e, (u8)(mipi_timing[vtotal] % 256));
|
||||
lt8911_i2c_write(client, 0x0f, (u8)(mipi_timing[vact] / 256));
|
||||
lt8911_i2c_write(client, 0x10, (u8)(mipi_timing[vact] % 256));
|
||||
lt8911_i2c_write(client, 0x11, (u8)(mipi_timing[htotal] / 256));
|
||||
lt8911_i2c_write(client, 0x12, (u8)(mipi_timing[htotal] % 256));
|
||||
lt8911_i2c_write(client, 0x13, (u8)(mipi_timing[hact] / 256));
|
||||
lt8911_i2c_write(client, 0x14, (u8)(mipi_timing[hact] % 256));
|
||||
lt8911_i2c_write(client, 0x15, (u8)(mipi_timing[vs] % 256));
|
||||
lt8911_i2c_write(client, 0x16, (u8)(mipi_timing[hs] % 256));
|
||||
lt8911_i2c_write(client, 0x17, (u8)(mipi_timing[vfp] / 256));
|
||||
lt8911_i2c_write(client, 0x18, (u8)(mipi_timing[vfp] % 256));
|
||||
lt8911_i2c_write(client, 0x19, (u8)(mipi_timing[hfp] / 256));
|
||||
lt8911_i2c_write(client, 0x1a, (u8)(mipi_timing[hfp] % 256));
|
||||
}
|
||||
|
||||
static void lt8911exb_cfg_set_edp_timing(struct i2c_mipi_dsi *md)
|
||||
{
|
||||
struct i2c_client *client = md->client;
|
||||
|
||||
/* lt8911exb eDP video timing configuration */
|
||||
lt8911_i2c_write(client, 0xff, 0xa8);
|
||||
lt8911_i2c_write(client, 0x2d, 0x88);
|
||||
lt8911_i2c_write(client, 0x05,
|
||||
(u8)(mipi_timing[htotal] / 256));
|
||||
lt8911_i2c_write(client, 0x06,
|
||||
(u8)(mipi_timing[htotal] % 256));
|
||||
lt8911_i2c_write(client, 0x07,
|
||||
(u8)((mipi_timing[hs] + mipi_timing[hbp]) / 256));
|
||||
lt8911_i2c_write(client, 0x08,
|
||||
(u8)((mipi_timing[hs] + mipi_timing[hbp]) % 256));
|
||||
lt8911_i2c_write(client, 0x09,
|
||||
(u8)(mipi_timing[hs] / 256));
|
||||
lt8911_i2c_write(client, 0x0a,
|
||||
(u8)(mipi_timing[hs] % 256));
|
||||
lt8911_i2c_write(client, 0x0b,
|
||||
(u8)(mipi_timing[hact] / 256));
|
||||
lt8911_i2c_write(client, 0x0c,
|
||||
(u8)(mipi_timing[hact] % 256));
|
||||
lt8911_i2c_write(client, 0x0d,
|
||||
(u8)(mipi_timing[vtotal] / 256));
|
||||
lt8911_i2c_write(client, 0x0e,
|
||||
(u8)(mipi_timing[vtotal] % 256));
|
||||
lt8911_i2c_write(client, 0x11,
|
||||
(u8)((mipi_timing[vs] + mipi_timing[vbp]) / 256));
|
||||
lt8911_i2c_write(client, 0x12,
|
||||
(u8)((mipi_timing[vs] + mipi_timing[vbp]) % 256));
|
||||
lt8911_i2c_write(client, 0x14,
|
||||
(u8)(mipi_timing[vs] % 256));
|
||||
lt8911_i2c_write(client, 0x15,
|
||||
(u8)(mipi_timing[vact] / 256));
|
||||
lt8911_i2c_write(client, 0x16,
|
||||
(u8)(mipi_timing[vact] % 256));
|
||||
}
|
||||
|
||||
static void lt8911exb_cfg_init_regs(struct i2c_mipi_dsi *md)
|
||||
{
|
||||
u32 val = 0;
|
||||
u8 i, pcr_pll_postdiv, pcr_m;
|
||||
struct i2c_client *client = md->client;
|
||||
u8 swing_ds1[13][2] = {
|
||||
{ 0x83, 0x00 }, /* 27.8 mA */
|
||||
{ 0x82, 0xe0 }, /* 26.2 mA */
|
||||
{ 0x82, 0xc0 }, /* 24.6 mA */
|
||||
{ 0x82, 0xa0 }, /* 23.0 mA */
|
||||
{ 0x82, 0x80 }, /* 21.4 mA */
|
||||
{ 0x82, 0x40 }, /* 18.2 mA */
|
||||
{ 0x82, 0x20 }, /* 16.6 mA */
|
||||
{ 0x82, 0x00 }, /* 15.0 mA */
|
||||
{ 0x81, 0x00 }, /* 12.8 mA */
|
||||
{ 0x80, 0xe0 }, /* 11.2 mA */
|
||||
{ 0x80, 0xc0 }, /* 9.6 mA */
|
||||
{ 0x80, 0xa0 }, /* 8 mA */
|
||||
{ 0x80, 0x80 } /* 6 mA */
|
||||
};
|
||||
|
||||
/* initialization */
|
||||
lt8911_i2c_write(client, 0xff, 0x81);
|
||||
lt8911_i2c_write(client, 0x49, 0xff);
|
||||
lt8911_i2c_write(client, 0xff, 0x82);
|
||||
lt8911_i2c_write(client, 0x5a, 0x0e);
|
||||
|
||||
/* MIPI Rx analog */
|
||||
lt8911_i2c_write(client, 0xff, 0x82);
|
||||
lt8911_i2c_write(client, 0x32, 0x51);
|
||||
lt8911_i2c_write(client, 0x35, 0x22);
|
||||
lt8911_i2c_write(client, 0x4c, 0x0c);
|
||||
lt8911_i2c_write(client, 0x4d, 0x00);
|
||||
|
||||
lt8911_i2c_write(client, 0x3a, 0x77);
|
||||
lt8911_i2c_write(client, 0x3b, 0x77);
|
||||
|
||||
/* dessc_pcr pll analog */
|
||||
lt8911_i2c_write(client, 0xff, 0x82);
|
||||
lt8911_i2c_write(client, 0x6a, 0x40);
|
||||
lt8911_i2c_write(client, 0x6b, 0x40);
|
||||
|
||||
if (mipi_timing[pclk_10khz] < 8800) {
|
||||
/* 0x44: pre-div = 2, pixel_clk = 44~88MHz */
|
||||
lt8911_i2c_write(client, 0x6e, 0x82);
|
||||
pcr_pll_postdiv = 0x08;
|
||||
} else {
|
||||
/* 0x40: pre-div = 1, pixel_clk = 88~176MHz */
|
||||
lt8911_i2c_write(client, 0x6e, 0x81);
|
||||
pcr_pll_postdiv = 0x04;
|
||||
}
|
||||
pcr_m = (u8)(mipi_timing[pclk_10khz] * pcr_pll_postdiv / 25 / 100);
|
||||
|
||||
/* dessc pll digital */
|
||||
lt8911_i2c_write(client, 0xff, 0x85);
|
||||
lt8911_i2c_write(client, 0xa9, 0x31);
|
||||
lt8911_i2c_write(client, 0xaa, 0x17);
|
||||
lt8911_i2c_write(client, 0xab, 0xba);
|
||||
lt8911_i2c_write(client, 0xac, 0xe1);
|
||||
lt8911_i2c_write(client, 0xad, 0x47);
|
||||
lt8911_i2c_write(client, 0xae, 0x01);
|
||||
lt8911_i2c_write(client, 0xae, 0x11);
|
||||
|
||||
/* digital top */
|
||||
lt8911_i2c_write(client, 0xff, 0x85);
|
||||
lt8911_i2c_write(client, 0xc0, 0x01);/* select mipi rx */
|
||||
|
||||
if (md->edp_depth == 6)
|
||||
val = 0xd0; /* enable dither */
|
||||
else if (md->edp_depth == 8)
|
||||
val = 0x00; /* disable dither */
|
||||
lt8911_i2c_write(client, 0xb0, val);
|
||||
|
||||
/* MIPI Rx digital */
|
||||
lt8911_i2c_write(client, 0xff, 0xd0);
|
||||
/* 0: 4 lane; 1: 1 lane; 2: 2 lane; 3: 3 lane */
|
||||
lt8911_i2c_write(client, 0x00, md->mipi_lane_cnt % 4);
|
||||
lt8911_i2c_write(client, 0x02, 0x08);
|
||||
lt8911_i2c_write(client, 0x08, 0x00);
|
||||
lt8911_i2c_write(client, 0x0a, 0x12);/* pcr mode */
|
||||
lt8911_i2c_write(client, 0x0c, 0x40);
|
||||
|
||||
lt8911_i2c_write(client, 0x1c, 0x3a);
|
||||
lt8911_i2c_write(client, 0x31, 0x0a);
|
||||
|
||||
lt8911_i2c_write(client, 0x3f, 0x10);
|
||||
lt8911_i2c_write(client, 0x40, 0x20);
|
||||
lt8911_i2c_write(client, 0x41, 0x30);
|
||||
|
||||
#ifdef TEST_PATTERN
|
||||
lt8911_i2c_write(client, 0x26, pcr_m | 0x80);
|
||||
#else
|
||||
lt8911_i2c_write(client, 0x26, pcr_m);
|
||||
#endif
|
||||
|
||||
lt8911_i2c_write(client, 0x27, 0x28);
|
||||
lt8911_i2c_write(client, 0x28, 0xf8);
|
||||
|
||||
lt8911_i2c_write(client, 0xff, 0x81);/* pcr reset */
|
||||
lt8911_i2c_write(client, 0x03, 0x7b);
|
||||
lt8911_i2c_write(client, 0x03, 0xff);
|
||||
|
||||
/* Tx PLL 2.7GHz */
|
||||
lt8911_i2c_write(client, 0xff, 0x87);
|
||||
lt8911_i2c_write(client, 0x19, 0x31);
|
||||
lt8911_i2c_write(client, 0xff, 0x82);
|
||||
lt8911_i2c_write(client, 0x02, 0x42);
|
||||
lt8911_i2c_write(client, 0x03, 0x00);
|
||||
lt8911_i2c_write(client, 0x03, 0x01);
|
||||
lt8911_i2c_write(client, 0xff, 0x81);
|
||||
lt8911_i2c_write(client, 0x09, 0xfc);
|
||||
lt8911_i2c_write(client, 0x09, 0xfd);
|
||||
lt8911_i2c_write(client, 0xff, 0x87);
|
||||
lt8911_i2c_write(client, 0x0c, 0x11);
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
msleep(5);
|
||||
if (lt8911_i2c_read(client, 0x37) & 0x02) {
|
||||
DBG_FUNC("%s: lt8911exb tx pll locked\n",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
|
||||
DBG_FUNC("%s: lt8911exb tx pll unlocked\n", __func__);
|
||||
lt8911_i2c_write(client, 0xff, 0x81);
|
||||
lt8911_i2c_write(client, 0x09, 0xfc);
|
||||
lt8911_i2c_write(client, 0x09, 0xfd);
|
||||
lt8911_i2c_write(client, 0xff, 0x87);
|
||||
lt8911_i2c_write(client, 0x0c, 0x10);
|
||||
lt8911_i2c_write(client, 0x0c, 0x11);
|
||||
}
|
||||
|
||||
/* Tx PHY */
|
||||
lt8911_i2c_write(client, 0xff, 0x82);
|
||||
lt8911_i2c_write(client, 0x11, 0x00);
|
||||
lt8911_i2c_write(client, 0x13, 0x10);
|
||||
lt8911_i2c_write(client, 0x14, 0x0c);
|
||||
lt8911_i2c_write(client, 0x14, 0x08);
|
||||
lt8911_i2c_write(client, 0x13, 0x20);
|
||||
lt8911_i2c_write(client, 0xff, 0x82);
|
||||
lt8911_i2c_write(client, 0x0e, 0x25);
|
||||
lt8911_i2c_write(client, 0x12, 0xff);
|
||||
|
||||
/* eDP tx digital */
|
||||
lt8911_i2c_write(client, 0xff, 0xa8);
|
||||
|
||||
#ifdef TEST_PATTERN
|
||||
/* bit[2:0]: test panttern image mode */
|
||||
lt8911_i2c_write(client, 0x24, 0x50);
|
||||
/* bit[6:4]: test pattern color */
|
||||
lt8911_i2c_write(client, 0x25, 0x70);
|
||||
/* 0x50: pattern; 0x10: mipi video */
|
||||
lt8911_i2c_write(client, 0x27, 0x50);
|
||||
#else
|
||||
/* 0x50: pattern; 0x10: mipi video */
|
||||
lt8911_i2c_write(client, 0x27, 0x10);
|
||||
#endif
|
||||
|
||||
if (md->edp_depth == 6)
|
||||
val = 0x00;
|
||||
else if (md->edp_depth == 8)
|
||||
val = 0x10;
|
||||
lt8911_i2c_write(client, 0x17, val);
|
||||
lt8911_i2c_write(client, 0x18, val << 1);
|
||||
|
||||
lt8911_i2c_write(client, 0xff, 0xa0);
|
||||
lt8911_i2c_write(client, 0x00, 0x08);
|
||||
lt8911_i2c_write(client, 0x01, 0x00);
|
||||
|
||||
/* set eDP drive strength */
|
||||
lt8911_i2c_write(client, 0xff, 0x82);
|
||||
/* lane 0 tap0 */
|
||||
lt8911_i2c_write(client, 0x22, swing_ds1[0][0]);
|
||||
lt8911_i2c_write(client, 0x23, swing_ds1[0][1]);
|
||||
/* lane 0 tap1 */
|
||||
lt8911_i2c_write(client, 0x24, 0x80);
|
||||
lt8911_i2c_write(client, 0x25, 0x00);
|
||||
/* lane 1 tap0 */
|
||||
lt8911_i2c_write(client, 0x26, swing_ds1[0][0]);
|
||||
lt8911_i2c_write(client, 0x27, swing_ds1[0][1]);
|
||||
/* lane 1 tap1 */
|
||||
lt8911_i2c_write(client, 0x28, 0x80);
|
||||
lt8911_i2c_write(client, 0x29, 0x00);
|
||||
}
|
||||
|
||||
/*
|
||||
* MIPI signal from SoC should be ready before
|
||||
* configuring below video check setting
|
||||
*/
|
||||
static void lt8911exb_dbg_check_mipi_timing(struct i2c_mipi_dsi *md)
|
||||
{
|
||||
u32 val = 0;
|
||||
struct i2c_client *client = md->client;
|
||||
|
||||
/* MIPI byte clk check */
|
||||
lt8911_i2c_write(client, 0xff, 0x85);
|
||||
/* FM select byte clk */
|
||||
lt8911_i2c_write(client, 0x1d, 0x00);
|
||||
lt8911_i2c_write(client, 0x40, 0xf7);
|
||||
lt8911_i2c_write(client, 0x41, 0x30);
|
||||
/* eDP scramble mode; video chech from mipi */
|
||||
lt8911_i2c_write(client, 0xa1, 0x02);
|
||||
/* 0xf0: close scramble; 0xD0: open scramble */
|
||||
//lt8911_i2c_write(client, 0x17, 0xf0);
|
||||
|
||||
/* video check reset */
|
||||
lt8911_i2c_write(client, 0xff, 0x81);
|
||||
lt8911_i2c_write(client, 0x09, 0x7d);
|
||||
lt8911_i2c_write(client, 0x09, 0xfd);
|
||||
|
||||
lt8911_i2c_write(client, 0xff, 0x85);
|
||||
//msleep(200);
|
||||
msleep(10);
|
||||
if (lt8911_i2c_read(client, 0x50) == 0x03) {
|
||||
val = lt8911_i2c_read(client, 0x4d);
|
||||
val = (val << 8) + lt8911_i2c_read(client, 0x4e);
|
||||
val = (val << 8) + lt8911_i2c_read(client, 0x4f);
|
||||
/* MIPI clk = val * 1000 */
|
||||
DBG_FUNC("%s: video check: mipi clk = %d\n",
|
||||
__func__, val);
|
||||
} else {
|
||||
DBG_FUNC("%s: video check: mipi clk unstable",
|
||||
__func__);
|
||||
}
|
||||
|
||||
/* MIPI Vtotal check */
|
||||
val = lt8911_i2c_read(client, 0x76);
|
||||
val = (val << 8) + lt8911_i2c_read(client, 0x77);
|
||||
DBG_FUNC("%s: video check: Vtotal = %d\n",
|
||||
__func__, val);
|
||||
|
||||
/* MIPI word count check */
|
||||
lt8911_i2c_write(client, 0xff, 0xd0);
|
||||
val = lt8911_i2c_read(client, 0x82);
|
||||
val = (val << 8) + lt8911_i2c_read(client, 0x83);
|
||||
val = val / 3;
|
||||
DBG_FUNC("%s: video check: Hact(word counter) = %d\n",
|
||||
__func__, val);
|
||||
|
||||
/* MIPI Vact check */
|
||||
val = lt8911_i2c_read(client, 0x85);
|
||||
val = (val << 8) + lt8911_i2c_read(client, 0x86);
|
||||
DBG_FUNC("%s: video check: Vact = %d\n",
|
||||
__func__, val);
|
||||
}
|
||||
|
||||
static void lt8911exb_link_train_start(struct i2c_mipi_dsi *md)
|
||||
{
|
||||
struct i2c_client *client = md->client;
|
||||
|
||||
/* lt8911exb link training */
|
||||
lt8911_i2c_write(client, 0xff, 0x85);
|
||||
/* eDP scramble mode */
|
||||
lt8911_i2c_write(client, 0xa1, 0x02);
|
||||
|
||||
/* AUX setup */
|
||||
lt8911_i2c_write(client, 0xff, 0xac);
|
||||
/* soft link training */
|
||||
lt8911_i2c_write(client, 0x00, 0x60);
|
||||
lt8911_i2c_write(client, 0xff, 0xa6);
|
||||
lt8911_i2c_write(client, 0x2a, 0x00);
|
||||
|
||||
lt8911_i2c_write(client, 0xff, 0x81);
|
||||
lt8911_i2c_write(client, 0x07, 0xfe);
|
||||
lt8911_i2c_write(client, 0x07, 0xff);
|
||||
lt8911_i2c_write(client, 0x0a, 0xfc);
|
||||
lt8911_i2c_write(client, 0x0a, 0xfe);
|
||||
|
||||
/* link training */
|
||||
lt8911_i2c_write(client, 0xff, 0x85);
|
||||
lt8911_i2c_write(client, 0x1a, md->edp_lane_cnt);
|
||||
//lt8911_i2c_write(client, 0x13, 0xd1);
|
||||
lt8911_i2c_write(client, 0xff, 0xac);
|
||||
lt8911_i2c_write(client, 0x00, 0x64);
|
||||
lt8911_i2c_write(client, 0x01, 0x0a);
|
||||
lt8911_i2c_write(client, 0x0c, 0x85);
|
||||
lt8911_i2c_write(client, 0x0c, 0xc5);
|
||||
}
|
||||
|
||||
static void lt8911exb_link_train_get_result(struct i2c_mipi_dsi *md)
|
||||
{
|
||||
u32 i, val;
|
||||
struct i2c_client *client = md->client;
|
||||
|
||||
lt8911_i2c_write(client, 0xff, 0xac);
|
||||
for (i = 0; i < 10; i++) {
|
||||
val = lt8911_i2c_read(client, 0x82);
|
||||
if (val & 0x20) {
|
||||
if ((val & 0x1f) == 0x1e)
|
||||
DBG_FUNC("%s: link training succeeded\n",
|
||||
__func__);
|
||||
else
|
||||
DBG_FUNC("%s: link training failed\n",
|
||||
__func__);
|
||||
|
||||
DBG_FUNC("%s: panel link rate: %d\n", __func__,
|
||||
lt8911_i2c_read(client, 0x83));
|
||||
DBG_FUNC("%s: panel link count: %d\n", __func__,
|
||||
lt8911_i2c_read(client, 0x84));
|
||||
break;
|
||||
}
|
||||
DBG_FUNC("%s: link training ongoing...\n", __func__);
|
||||
msleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
/* panel_funcs */
|
||||
static int panel_prepare(struct drm_panel *panel)
|
||||
{
|
||||
int ret = 0;
|
||||
struct i2c_mipi_dsi *md = panel_to_md(panel);
|
||||
struct i2c_client *client = md->client;
|
||||
|
||||
DBG_FUNC("lt8911exb enter\n");
|
||||
|
||||
if(md->client == NULL){
|
||||
DBG_FUNC("lt8911exb i2c client still not ready\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = regulator_enable(md->vspn3v3);
|
||||
if(ret){
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = regulator_enable(md->hsvcc);
|
||||
if(ret){
|
||||
goto fail;
|
||||
}
|
||||
|
||||
//msleep(200);
|
||||
msleep(10);
|
||||
|
||||
lt8911_reset(md);
|
||||
|
||||
lt8911_i2c_write(client, 0xff, 0x81); /* 0x81: register bank */
|
||||
lt8911_i2c_write(client, 0x08, 0x7f);
|
||||
|
||||
DBG_FUNC("%s: lt8911exb chip ID: 0x%02x-0x%02x-0x%02x\n",
|
||||
__func__, lt8911_i2c_read(client, 0x00),
|
||||
lt8911_i2c_read(client, 0x01),
|
||||
lt8911_i2c_read(client, 0x02));
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
gpio_set_value(md->reset_pin, 0);
|
||||
regulator_disable(md->hsvcc);
|
||||
regulator_disable(md->vspn3v3);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int panel_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
int ret = 0;
|
||||
struct i2c_mipi_dsi *md = panel_to_md(panel);
|
||||
|
||||
DBG_FUNC("panel_unprepare enter\n");
|
||||
gpio_set_value(md->reset_pin, 0);
|
||||
|
||||
regulator_disable(md->hsvcc);
|
||||
regulator_disable(md->vspn3v3);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int panel_enable(struct drm_panel *panel)
|
||||
{
|
||||
int ret = 0;
|
||||
struct i2c_mipi_dsi *md = panel_to_md(panel);
|
||||
|
||||
DBG_FUNC("panel_unprepare enter\n");
|
||||
|
||||
gpio_set_value(md->backlight_pin, 1);
|
||||
|
||||
lt8911exb_cfg_set_mipi_timing(md);
|
||||
lt8911exb_cfg_set_edp_timing(md);
|
||||
lt8911exb_cfg_init_regs(md);
|
||||
lt8911exb_dbg_check_mipi_timing(md);
|
||||
lt8911exb_link_train_start(md);
|
||||
lt8911exb_link_train_get_result(md);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int panel_disable(struct drm_panel *panel)
|
||||
{
|
||||
int ret = 0;
|
||||
struct i2c_mipi_dsi *md = panel_to_md(panel);
|
||||
|
||||
DBG_FUNC("panel_disable enter\n");
|
||||
|
||||
gpio_set_value(md->backlight_pin, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int panel_get_modes(struct drm_panel *panel, struct drm_connector *connector)
|
||||
{
|
||||
struct i2c_mipi_dsi *md = panel_to_md(panel);
|
||||
const struct drm_display_mode *m = md->desc->display_mode;
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
DBG_FUNC("panel_get_modes enter\n");
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, m);
|
||||
if (!mode) {
|
||||
/*
|
||||
dev_err(pinfo->base.dev, "failed to add mode %ux%u@%u\n",
|
||||
m->hdisplay, m->vdisplay, drm_mode_vrefresh(m));
|
||||
*/
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
connector->display_info.width_mm = mode->width_mm;
|
||||
connector->display_info.height_mm = mode->height_mm;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs panel_funcs = {
|
||||
.prepare = panel_prepare,
|
||||
.unprepare = panel_unprepare,
|
||||
.enable = panel_enable,
|
||||
.disable = panel_disable,
|
||||
.get_modes = panel_get_modes,
|
||||
};
|
||||
|
||||
/* backlight */
|
||||
static int backlight_update(struct backlight_device *bd)
|
||||
{
|
||||
struct i2c_mipi_dsi *md = bl_get_data(bd);
|
||||
int brightness = bd->props.brightness;
|
||||
|
||||
if (bd->props.power != FB_BLANK_UNBLANK ||
|
||||
bd->props.fb_blank != FB_BLANK_UNBLANK ||
|
||||
(bd->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))) {
|
||||
brightness = 0;
|
||||
}
|
||||
|
||||
md->brightness = brightness;
|
||||
//i2c_md_write(md, REG_PWM, brightness);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct backlight_ops backlight_ops = {
|
||||
.options = BL_CORE_SUSPENDRESUME,
|
||||
.update_status = backlight_update,
|
||||
};
|
||||
|
||||
/**
|
||||
static int backlight_init(struct i2c_mipi_dsi *md)
|
||||
{
|
||||
struct device *dev = &md->client->dev;
|
||||
struct backlight_properties props;
|
||||
struct backlight_device *bd;
|
||||
|
||||
printk(KERN_ERR "=====Function %s line %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
memset(&props, 0, sizeof(props));
|
||||
props.type = BACKLIGHT_RAW;
|
||||
props.max_brightness = 255;
|
||||
bd = devm_backlight_device_register(dev, dev_name(dev),
|
||||
dev, md, &backlight_ops,
|
||||
&props);
|
||||
if (IS_ERR(bd)) {
|
||||
dev_err(dev, "failed to register backlight\n");
|
||||
return PTR_ERR(bd);
|
||||
}
|
||||
|
||||
bd->props.brightness = 255;
|
||||
backlight_update_status(bd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
static int i2c_md_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct i2c_mipi_dsi *md = g_lt8911_mipi_dsi;
|
||||
|
||||
DBG_FUNC("start");
|
||||
|
||||
i2c_set_clientdata(client, md);
|
||||
mutex_init(&md->mutex);
|
||||
md->client = client;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2c_md_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct i2c_mipi_dsi *md = i2c_get_clientdata(i2c);
|
||||
|
||||
DBG_FUNC();
|
||||
|
||||
mipi_dsi_detach(md->dsi);
|
||||
drm_panel_remove(&md->panel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void i2c_md_shutdown(struct i2c_client *i2c)
|
||||
{
|
||||
struct i2c_mipi_dsi *md = i2c_get_clientdata(i2c);
|
||||
|
||||
DBG_FUNC();
|
||||
|
||||
mipi_dsi_detach(md->dsi);
|
||||
drm_panel_remove(&md->panel);
|
||||
}
|
||||
|
||||
static int lt8911_parse_dt(struct i2c_mipi_dsi *md)
|
||||
{
|
||||
int ret = -1;
|
||||
struct mipi_dsi_device *dsi = md->dsi;
|
||||
struct device_node *np = dsi->dev.of_node;
|
||||
|
||||
md->hsvcc = devm_regulator_get(&dsi->dev, "hsvcc");
|
||||
if (IS_ERR(md->hsvcc))
|
||||
return dev_err_probe(&dsi->dev, PTR_ERR(md->hsvcc),
|
||||
"Failed to request hsvcc regulator\n");
|
||||
|
||||
md->vspn3v3 = devm_regulator_get(&dsi->dev, "vspn3v3");
|
||||
if (IS_ERR(md->vspn3v3))
|
||||
return dev_err_probe(&dsi->dev, PTR_ERR(md->vspn3v3),
|
||||
"Failed to request vspn3v3 regulator\n");
|
||||
|
||||
md->backlight_pin = of_get_named_gpio_flags(np,
|
||||
"lt8911,backlight-gpio",
|
||||
0, NULL);
|
||||
if (!gpio_is_valid(md->backlight_pin)) {
|
||||
DBG_FUNC("%s: backlight-gpio is invalid\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = devm_gpio_request_one(&dsi->dev,
|
||||
md->backlight_pin,
|
||||
GPIOF_DIR_OUT, NULL);
|
||||
if (ret) {
|
||||
DBG_FUNC("%s: failed to request backlight gpio\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
gpio_set_value(md->backlight_pin, 0);
|
||||
DBG_FUNC("%s: succeed to init backlight gpio\n", __func__);
|
||||
|
||||
md->irq_pin = of_get_named_gpio_flags(np,
|
||||
"lt8911,irq-gpio", 0, NULL);
|
||||
if (!gpio_is_valid(md->irq_pin)) {
|
||||
DBG_FUNC("%s: irq-gpio is invalid\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = devm_gpio_request_one(&dsi->dev,
|
||||
md->irq_pin,
|
||||
GPIOF_DIR_IN, NULL);
|
||||
if (ret) {
|
||||
DBG_FUNC("%s: failed to request irq gpio\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
DBG_FUNC("%s: succeed to init irq gpio\n", __func__);
|
||||
|
||||
ret = of_property_read_u32(np, "lt8911,rst-delay-ms",
|
||||
&md->rst_delay_ms);
|
||||
if (ret < 0) {
|
||||
DBG_FUNC("%s: no rst-delay-ms property in dts\n",
|
||||
__func__);
|
||||
md->rst_delay_ms = 100;
|
||||
}
|
||||
|
||||
md->reset_pin = of_get_named_gpio_flags(np,
|
||||
"lt8911,reset-gpio", 0, NULL);
|
||||
if (!gpio_is_valid(md->reset_pin)) {
|
||||
DBG_FUNC("%s: reset-gpio is invalid\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = devm_gpio_request_one(&dsi->dev,
|
||||
md->reset_pin,
|
||||
GPIOF_DIR_OUT, NULL);
|
||||
if (ret) {
|
||||
DBG_FUNC("%s: failed to request reset gpio\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
gpio_set_value(md->reset_pin, 0);
|
||||
DBG_FUNC("%s: succeed to init reset gpio\n", __func__);
|
||||
|
||||
if (of_property_read_u32(np, "lt8911,edp-lane-cnt",
|
||||
&md->edp_lane_cnt)) {
|
||||
DBG_FUNC("%s: miss edp-lane-cnt property in dts\n",
|
||||
__func__);
|
||||
md->edp_lane_cnt = 2; /* default value */
|
||||
}
|
||||
|
||||
if (of_property_read_u32(np, "lt8911,mipi-lane-cnt",
|
||||
&md->mipi_lane_cnt)) {
|
||||
DBG_FUNC("%s: miss mipi-lane-cnt property in dts\n",
|
||||
__func__);
|
||||
md->mipi_lane_cnt = 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* eDP panel color depth:
|
||||
* 6 bit: 262K colors
|
||||
* 8 bit: 16.7M colors
|
||||
*/
|
||||
if (of_property_read_u32(np, "lt8911,edp-depth",
|
||||
&md->edp_depth)) {
|
||||
DBG_FUNC("%s: miss edp-depth property in dts\n",
|
||||
__func__);
|
||||
md->edp_depth = 8;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id i2c_md_of_ids[] = {
|
||||
{
|
||||
.compatible = "i2c,lt8911",
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, i2c_md_of_ids);
|
||||
|
||||
static struct i2c_driver i2c_md_driver = {
|
||||
.driver = {
|
||||
.name = "i2c_mipi_dsi",
|
||||
.of_match_table = i2c_md_of_ids,
|
||||
},
|
||||
.probe = i2c_md_probe,
|
||||
.remove = i2c_md_remove,
|
||||
.shutdown = i2c_md_shutdown,
|
||||
};
|
||||
|
||||
module_i2c_driver(i2c_md_driver);
|
||||
|
||||
static int lt8911_dsi_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
int ret;
|
||||
struct i2c_mipi_dsi *ctx;
|
||||
|
||||
ctx = g_lt8911_mipi_dsi;
|
||||
|
||||
if(ctx == NULL){
|
||||
ctx = devm_kzalloc(&dsi->dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
g_lt8911_mipi_dsi = ctx;
|
||||
}
|
||||
|
||||
if(ctx->client == NULL){
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
ctx->dsi = dsi;
|
||||
ctx->desc = <8911_panel_data;
|
||||
ret = lt8911_parse_dt(ctx);
|
||||
if (ret) {
|
||||
DBG_FUNC("%s: failed to parse device tree\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsi->mode_flags = ctx->desc->mode_flags;
|
||||
dsi->format = ctx->desc->format;
|
||||
dsi->lanes = ctx->desc->lanes;
|
||||
|
||||
mipi_dsi_set_drvdata(dsi, ctx);
|
||||
|
||||
//ctx->panel_data->set_dsi(ctx->dsi);
|
||||
drm_panel_init(&ctx->panel, &dsi->dev, &panel_funcs, DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ret = drm_panel_of_backlight(&ctx->panel);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_panel_add(&ctx->panel);
|
||||
|
||||
//backlight_init(ctx);
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0)
|
||||
{
|
||||
drm_panel_remove(&ctx->panel);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lt8911_dsi_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct i2c_mipi_dsi *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
|
||||
mipi_dsi_detach(dsi);
|
||||
drm_panel_remove(&ctx->panel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lt8911_dsi_shutdown(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static const struct of_device_id lt8911_of_match[] = {
|
||||
{.compatible = "i2c_dsi,lt8911", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lt8911_of_match);
|
||||
|
||||
static struct mipi_dsi_driver lt8911_dsi_driver = {
|
||||
.probe = lt8911_dsi_probe,
|
||||
.remove = lt8911_dsi_remove,
|
||||
.shutdown = lt8911_dsi_shutdown,
|
||||
.driver = {
|
||||
.name = "panel-lt8911",
|
||||
.of_match_table = lt8911_of_match,
|
||||
},
|
||||
};
|
||||
module_mipi_dsi_driver(lt8911_dsi_driver);
|
||||
|
||||
MODULE_DESCRIPTION("LT8911 Controller Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
87
drivers/gpu/drm/panel/panel-lt8911.h
Normal file
87
drivers/gpu/drm/panel/panel-lt8911.h
Normal file
@@ -0,0 +1,87 @@
|
||||
#ifndef __MIPI_DSI_H__
|
||||
#define __MIPI_DSI_H__
|
||||
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_modes.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
|
||||
#if 1
|
||||
#define DBG_FUNC(format, x...) printk(KERN_ERR "[DSI]%s:" format"\n", __func__, ##x)
|
||||
#define DBG_PRINT(format, x...) printk(KERN_ERR "[DSI]" format"\n", ##x)
|
||||
#else
|
||||
#define DBG_FUNC(format, x...)
|
||||
#define DBG_PRINT(format, x...)
|
||||
#endif
|
||||
|
||||
#define DSI_DRIVER_NAME "i2c_mipi_dsi"
|
||||
|
||||
#define DSI_DCS_WRITE(dsi, seq...) \
|
||||
{ \
|
||||
int ret = 0; \
|
||||
const u8 d[] = { seq }; \
|
||||
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
struct panel_data {
|
||||
struct drm_display_mode *display_mode;
|
||||
unsigned long mode_flags;
|
||||
enum mipi_dsi_pixel_format format;
|
||||
unsigned int lanes;
|
||||
};
|
||||
|
||||
struct i2c_mipi_dsi {
|
||||
struct i2c_client *client;
|
||||
struct mutex mutex;
|
||||
|
||||
struct regulator *hsvcc;
|
||||
struct regulator *vspn3v3;
|
||||
|
||||
// panel
|
||||
struct drm_panel panel;
|
||||
struct panel_data *desc;
|
||||
|
||||
// dsi
|
||||
struct mipi_dsi_device *dsi;
|
||||
|
||||
int backlight_pin;
|
||||
int irq_pin;
|
||||
int reset_pin;
|
||||
int enable_pin;
|
||||
int rst_delay_ms;
|
||||
|
||||
u32 edp_lane_cnt;
|
||||
u32 mipi_lane_cnt;
|
||||
u32 edp_depth;
|
||||
|
||||
// backlight
|
||||
int brightness;
|
||||
};
|
||||
|
||||
#define panel_to_md(_p) container_of(_p, struct i2c_mipi_dsi, panel)
|
||||
|
||||
#endif /*End of header guard macro */
|
||||
0
drivers/gpu/drm/verisilicon/vs_dc.c
Normal file → Executable file
0
drivers/gpu/drm/verisilicon/vs_dc.c
Normal file → Executable file
25
drivers/input/hall/mh248.c
Normal file → Executable file
25
drivers/input/hall/mh248.c
Normal file → Executable file
@@ -68,17 +68,17 @@ static irqreturn_t hall_mh248_interrupt(int irq, void *dev_id)
|
||||
int gpio_value = 0;
|
||||
|
||||
gpio_value = gpio_get_value(mh248->gpio_pin);
|
||||
if ((gpio_value != mh248->active_value) &&
|
||||
(mh248->is_suspend == 0)) {
|
||||
input_report_key(mh248->hall_input, KEY_SLEEP, 1);
|
||||
if ((gpio_value != mh248->active_value) ) {
|
||||
//input_report_key(mh248->hall_input, KEY_SLEEP, 1);
|
||||
//input_sync(mh248->hall_input);
|
||||
//input_report_key(mh248->hall_input, KEY_SLEEP, 0);
|
||||
input_report_switch(mh248->hall_input, SW_LID, 1);
|
||||
input_sync(mh248->hall_input);
|
||||
input_report_key(mh248->hall_input, KEY_SLEEP, 0);
|
||||
input_sync(mh248->hall_input);
|
||||
} else if ((gpio_value == mh248->active_value) &&
|
||||
(mh248->is_suspend == 1)) {
|
||||
input_report_key(mh248->hall_input, KEY_WAKEUP, 1);
|
||||
input_sync(mh248->hall_input);
|
||||
input_report_key(mh248->hall_input, KEY_WAKEUP, 0);
|
||||
} else if ((gpio_value == mh248->active_value) ) {
|
||||
//input_report_key(mh248->hall_input, KEY_WAKEUP, 1);
|
||||
//input_sync(mh248->hall_input);
|
||||
//input_report_key(mh248->hall_input, KEY_WAKEUP, 0);
|
||||
input_report_switch(mh248->hall_input, SW_LID, 0);
|
||||
input_sync(mh248->hall_input);
|
||||
}
|
||||
|
||||
@@ -135,8 +135,9 @@ static int hall_mh248_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
mh248->hall_input->name = "hall wake key";
|
||||
input_set_capability(mh248->hall_input, EV_KEY, KEY_SLEEP);
|
||||
input_set_capability(mh248->hall_input, EV_KEY, KEY_WAKEUP);
|
||||
//input_set_capability(mh248->hall_input, EV_KEY, KEY_SLEEP);
|
||||
//input_set_capability(mh248->hall_input, EV_KEY, KEY_WAKEUP);
|
||||
input_set_capability(mh248->hall_input, EV_SW, SW_LID);
|
||||
|
||||
ret = input_register_device(mh248->hall_input);
|
||||
if (ret) {
|
||||
|
||||
0
drivers/phy/synopsys/phy-dw-mipi-dphy.c
Normal file → Executable file
0
drivers/phy/synopsys/phy-dw-mipi-dphy.c
Normal file → Executable file
0
drivers/pinctrl/thead/pinctrl-light.c
Normal file → Executable file
0
drivers/pinctrl/thead/pinctrl-light.c
Normal file → Executable file
11
kernel/power/hibernate.c
Normal file → Executable file
11
kernel/power/hibernate.c
Normal file → Executable file
@@ -42,6 +42,7 @@ static int nohibernate;
|
||||
static int resume_wait;
|
||||
static unsigned int resume_delay;
|
||||
static char resume_file[256] = CONFIG_PM_STD_PARTITION;
|
||||
static int resume_keep_sign;
|
||||
dev_t swsusp_resume_device;
|
||||
sector_t swsusp_resume_block;
|
||||
__visible int in_suspend __nosavedata;
|
||||
@@ -843,7 +844,7 @@ int hibernate(void)
|
||||
unlock_device_hotplug();
|
||||
if (snapshot_test) {
|
||||
pm_pr_dbg("Checking hibernation image\n");
|
||||
error = swsusp_check();
|
||||
error = swsusp_check(0);
|
||||
if (!error)
|
||||
error = load_image_and_restore();
|
||||
}
|
||||
@@ -1040,7 +1041,7 @@ static int software_resume(void)
|
||||
MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device));
|
||||
|
||||
pm_pr_dbg("Looking for hibernation image.\n");
|
||||
error = swsusp_check();
|
||||
error = swsusp_check(resume_keep_sign);
|
||||
if (error)
|
||||
goto Unlock;
|
||||
|
||||
@@ -1449,6 +1450,11 @@ static int __init nohibernate_setup(char *str)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init resume_keepsign_setup(char *str)
|
||||
{
|
||||
resume_keep_sign = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("noresume", noresume_setup);
|
||||
__setup("resume_offset=", resume_offset_setup);
|
||||
@@ -1457,3 +1463,4 @@ __setup("hibernate=", hibernate_setup);
|
||||
__setup("resumewait", resumewait_setup);
|
||||
__setup("resumedelay=", resumedelay_setup);
|
||||
__setup("nohibernate", nohibernate_setup);
|
||||
__setup("resume_keepsign", resume_keepsign_setup);
|
||||
|
||||
2
kernel/power/power.h
Normal file → Executable file
2
kernel/power/power.h
Normal file → Executable file
@@ -170,7 +170,7 @@ extern int swsusp_swap_in_use(void);
|
||||
#define SF_CRC32_MODE 4
|
||||
|
||||
/* kernel/power/hibernate.c */
|
||||
extern int swsusp_check(void);
|
||||
extern int swsusp_check(int keep_sign);
|
||||
extern void swsusp_free(void);
|
||||
extern int swsusp_read(unsigned int *flags_p);
|
||||
extern int swsusp_write(unsigned int flags);
|
||||
|
||||
0
kernel/power/snapshot.c
Normal file → Executable file
0
kernel/power/snapshot.c
Normal file → Executable file
21
kernel/power/swap.c
Normal file → Executable file
21
kernel/power/swap.c
Normal file → Executable file
@@ -634,7 +634,7 @@ static int lzo_compress_threadfn(void *data)
|
||||
d->wrk);
|
||||
lzo_head = (struct hib_lzo_header *)d->cmp;
|
||||
lzo_head->cmp_len = d->cmp_len;
|
||||
lzo_head->unc_crc32 = crc32_le(0,d->cmp + LZO_HEADER, d->cmp_len);
|
||||
lzo_head->unc_crc32 = crc32_le(0,d->unc, d->unc_len);
|
||||
atomic_set(&d->stop, 1);
|
||||
wake_up(&d->done);
|
||||
}
|
||||
@@ -1087,7 +1087,7 @@ static int lzo_decompress_threadfn(void *data)
|
||||
d->ret = lzo1x_decompress_safe(d->cmp + LZO_HEADER, d->cmp_len,
|
||||
d->unc, &d->unc_len);
|
||||
|
||||
unc_crc32 = crc32_le(0,d->cmp + LZO_HEADER, d->cmp_len);
|
||||
unc_crc32 = crc32_le(0,d->unc, d->unc_len);
|
||||
if(unc_crc32 != get_header_crc32((struct hib_lzo_header *)&d->cmp) ) {
|
||||
d->crc32_err++;
|
||||
}
|
||||
@@ -1449,9 +1449,10 @@ int swsusp_mark_sign_retry(void)
|
||||
}
|
||||
/**
|
||||
* swsusp_check - Check for swsusp signature in the resume device
|
||||
* @keep_sign : indicate for reset wap signature, for resume used as fast bootup
|
||||
*/
|
||||
|
||||
int swsusp_check(void)
|
||||
int swsusp_check(int keep_sign)
|
||||
{
|
||||
int error;
|
||||
void *holder;
|
||||
@@ -1473,13 +1474,13 @@ int swsusp_check(void)
|
||||
swsusp_can_retry = true;
|
||||
else
|
||||
swsusp_can_retry = false;
|
||||
|
||||
memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
|
||||
/* Reset swap signature now */
|
||||
error = hib_submit_io(REQ_OP_WRITE, REQ_SYNC,
|
||||
swsusp_resume_block,
|
||||
swsusp_header, NULL);
|
||||
|
||||
if(!keep_sign) {
|
||||
memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
|
||||
/* Reset swap signature now */
|
||||
error = hib_submit_io(REQ_OP_WRITE, REQ_SYNC,
|
||||
swsusp_resume_block,
|
||||
swsusp_header, NULL);
|
||||
}
|
||||
} else {
|
||||
error = -EINVAL;
|
||||
}
|
||||
|
||||
0
kernel/trace/ftrace.c
Normal file → Executable file
0
kernel/trace/ftrace.c
Normal file → Executable file
0
kernel/trace/trace.c
Normal file → Executable file
0
kernel/trace/trace.c
Normal file → Executable file
Reference in New Issue
Block a user