Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patches for the DSI touchscreen being shifted by 1 pixel #5840

Draft
wants to merge 8 commits into
base: rpi-6.1.y
Choose a base branch
from
83 changes: 74 additions & 9 deletions drivers/gpu/drm/bridge/tc358762.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
*/

#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of_graph.h>
#include <linux/regulator/consumer.h>
Expand Down Expand Up @@ -40,8 +42,23 @@
#define DSI_LANEENABLE 0x0210 /* Enables each lane */
#define DSI_RX_START 1

/* LCDC/DPI Host Registers */
#define LCDCTRL 0x0420
/* LCDC/DPI Host Registers, based on guesswork that this matches TC358764 */
#define LCDCTRL 0x0420 /* Video Path Control */
#define LCDCTRL_MSF BIT(0) /* Magic square in RGB666 */
#define LCDCTRL_VTGEN BIT(4)/* Use chip clock for timing */
#define LCDCTRL_UNK6 BIT(6) /* Unknown */
#define LCDCTRL_EVTMODE BIT(5) /* Event mode */
#define LCDCTRL_RGB888 BIT(8) /* RGB888 mode */
#define LCDCTRL_HSPOL BIT(17) /* Polarity of HSYNC signal */
#define LCDCTRL_DEPOL BIT(18) /* Polarity of DE signal */
#define LCDCTRL_VSPOL BIT(19) /* Polarity of VSYNC signal */
#define LCDCTRL_VSDELAY(v) (((v) & 0xfff) << 20) /* VSYNC delay */

/* First parameter is in the 16bits, second is in the top 16bits */
#define LCD_HS_HBP 0x0424
#define LCD_HDISP_HFP 0x0428
#define LCD_VS_VBP 0x042c
#define LCD_VDISP_VFP 0x0430

/* SPI Master Registers */
#define SPICMR 0x0450
Expand All @@ -63,6 +80,8 @@ struct tc358762 {
struct drm_bridge bridge;
struct regulator *regulator;
struct drm_bridge *panel_bridge;
struct gpio_desc *reset_gpio;
struct drm_display_mode mode;
bool pre_enabled;
int error;
};
Expand Down Expand Up @@ -103,6 +122,8 @@ static inline struct tc358762 *bridge_to_tc358762(struct drm_bridge *bridge)

static int tc358762_init(struct tc358762 *ctx)
{
u32 lcdctrl;

tc358762_write(ctx, DSI_LANEENABLE,
LANEENABLE_L0EN | LANEENABLE_CLEN);
tc358762_write(ctx, PPI_D0S_CLRSIPOCOUNT, 5);
Expand All @@ -112,8 +133,28 @@ static int tc358762_init(struct tc358762 *ctx)
tc358762_write(ctx, PPI_LPTXTIMECNT, LPX_PERIOD);

tc358762_write(ctx, SPICMR, 0x00);
tc358762_write(ctx, LCDCTRL, 0x00100150);

lcdctrl = LCDCTRL_VSDELAY(1) | LCDCTRL_RGB888 |
LCDCTRL_UNK6 | LCDCTRL_VTGEN;

if (ctx->mode.flags & DRM_MODE_FLAG_NHSYNC)
lcdctrl |= LCDCTRL_HSPOL;

if (ctx->mode.flags & DRM_MODE_FLAG_NVSYNC)
lcdctrl |= LCDCTRL_VSPOL;

tc358762_write(ctx, LCDCTRL, lcdctrl);

tc358762_write(ctx, SYSCTRL, 0x040f);

tc358762_write(ctx, LCD_HS_HBP, (ctx->mode.hsync_end - ctx->mode.hsync_start) |
((ctx->mode.htotal - ctx->mode.hsync_end) << 16));
tc358762_write(ctx, LCD_HDISP_HFP, ctx->mode.hdisplay |
((ctx->mode.hsync_start - ctx->mode.hdisplay) << 16));
tc358762_write(ctx, LCD_VS_VBP, (ctx->mode.vsync_end - ctx->mode.vsync_start) |
((ctx->mode.vtotal - ctx->mode.vsync_end) << 16));
tc358762_write(ctx, LCD_VDISP_VFP, ctx->mode.vdisplay |
((ctx->mode.vsync_start - ctx->mode.vdisplay) << 16));
msleep(100);

tc358762_write(ctx, PPI_STARTPPI, PPI_START_FUNCTION);
Expand All @@ -124,7 +165,7 @@ static int tc358762_init(struct tc358762 *ctx)
return tc358762_clear_error(ctx);
}

static void tc358762_post_disable(struct drm_bridge *bridge)
static void tc358762_post_disable(struct drm_bridge *bridge, struct drm_bridge_state *state)
{
struct tc358762 *ctx = bridge_to_tc358762(bridge);
int ret;
Expand All @@ -138,12 +179,15 @@ static void tc358762_post_disable(struct drm_bridge *bridge)

ctx->pre_enabled = false;

if (ctx->reset_gpio)
gpiod_set_value_cansleep(ctx->reset_gpio, 0);

ret = regulator_disable(ctx->regulator);
if (ret < 0)
dev_err(ctx->dev, "error disabling regulators (%d)\n", ret);
}

static void tc358762_pre_enable(struct drm_bridge *bridge)
static void tc358762_pre_enable(struct drm_bridge *bridge, struct drm_bridge_state *state)
{
struct tc358762 *ctx = bridge_to_tc358762(bridge);
int ret;
Expand All @@ -152,11 +196,14 @@ static void tc358762_pre_enable(struct drm_bridge *bridge)
if (ret < 0)
dev_err(ctx->dev, "error enabling regulators (%d)\n", ret);

if (ctx->reset_gpio) {
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
usleep_range(5000, 10000);
}

ret = tc358762_init(ctx);
if (ret < 0)
dev_err(ctx->dev, "error initializing bridge (%d)\n", ret);

ctx->pre_enabled = true;
}

static int tc358762_attach(struct drm_bridge *bridge,
Expand All @@ -168,10 +215,23 @@ static int tc358762_attach(struct drm_bridge *bridge,
bridge, flags);
}

static void tc358762_bridge_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
const struct drm_display_mode *adj)
{
struct tc358762 *ctx = bridge_to_tc358762(bridge);

drm_mode_copy(&ctx->mode, mode);
}

static const struct drm_bridge_funcs tc358762_bridge_funcs = {
.post_disable = tc358762_post_disable,
.pre_enable = tc358762_pre_enable,
.atomic_post_disable = tc358762_post_disable,
.atomic_pre_enable = tc358762_pre_enable,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_reset = drm_atomic_helper_bridge_reset,
.attach = tc358762_attach,
.mode_set = tc358762_bridge_mode_set,
};

static int tc358762_parse_dt(struct tc358762 *ctx)
Expand All @@ -185,6 +245,11 @@ static int tc358762_parse_dt(struct tc358762 *ctx)

ctx->panel_bridge = panel_bridge;

/* Reset GPIO is optional */
ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(ctx->reset_gpio))
return PTR_ERR(ctx->reset_gpio);

return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/panel/panel-simple.c
Original file line number Diff line number Diff line change
Expand Up @@ -3246,7 +3246,7 @@ static const struct drm_display_mode raspberrypi_7inch_mode = {
.hdisplay = 800,
.hsync_start = 800 + 59,
.hsync_end = 800 + 59 + 2,
.htotal = 800 + 59 + 2 + 46,
.htotal = 800 + 59 + 2 + 44,
.vdisplay = 480,
.vsync_start = 480 + 7,
.vsync_end = 480 + 7 + 2,
Expand Down