diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README index 64aab639e4984..52bc515e0a5ad 100644 --- a/arch/arm/boot/dts/overlays/README +++ b/arch/arm/boot/dts/overlays/README @@ -6195,8 +6195,8 @@ Params: 2_8_inch 2.8" 480x640 11_9_inch 11.9" 320x1480 13_3_inch_4lane 13.3" 1920x1080 4lane 13_3_inch_2lane 13.3" 1920x1080 2lane - auto_detect Automatic panel detection (1200x1920 or - 1920x1200 at 30fps/60fps) + 10_1_inchE_4lane 10.1" E 1920x1200 60fps 4lane + 10_1_inchE_2lane 10.1" E 1920x1200 30fps 2lane i2c1 Use i2c-1 with jumper wires from GPIOs 2&3 disable_touch Disable the touch controller rotation Set the panel orientation property diff --git a/arch/arm/boot/dts/overlays/vc4-kms-dsi-waveshare-panel-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-dsi-waveshare-panel-overlay.dts index d41c9dfe810f4..5c1cce1dddceb 100644 --- a/arch/arm/boot/dts/overlays/vc4-kms-dsi-waveshare-panel-overlay.dts +++ b/arch/arm/boot/dts/overlays/vc4-kms-dsi-waveshare-panel-overlay.dts @@ -136,7 +136,10 @@ 7_0_inchH = <&panel>, "compatible=waveshare,7.0inch-h-panel", <&touch>, "touchscreen-swapped-x-y?", <&touch>, "touchscreen-inverted-x?"; - auto_detect = <&panel>, "compatible=waveshare,automatic-detection-panel", + 10_1_inchE_4lane = <&panel>, "compatible=waveshare,10.1inch-e-4lane-panel", + <&touch>, "touchscreen-swapped-x-y?", + <&touch>, "touchscreen-inverted-x?"; + 10_1_inchE_2lane = <&panel>, "compatible=waveshare,10.1inch-e-2lane-panel", <&touch>, "touchscreen-swapped-x-y?", <&touch>, "touchscreen-inverted-x?"; i2c1 = <&i2c_frag>, "target:0=",<&i2c1>, diff --git a/drivers/gpu/drm/panel/panel-waveshare-dsi.c b/drivers/gpu/drm/panel/panel-waveshare-dsi.c index 6ef696f0aa632..563f77c5f0aa2 100644 --- a/drivers/gpu/drm/panel/panel-waveshare-dsi.c +++ b/drivers/gpu/drm/panel/panel-waveshare-dsi.c @@ -30,7 +30,6 @@ struct ws_panel { struct i2c_client *i2c; const struct drm_display_mode *mode; enum drm_panel_orientation orientation; - int lanes; }; struct ws_panel_data { @@ -349,30 +348,6 @@ static const struct ws_panel_data ws_panel_7_0_h_data = { /* 10.1inch DSI LCD (E) * https://www.waveshare.com/10.1inch-dsi-lcd-e.htm */ -static const struct drm_display_mode ws_panel_1200x1920_60fps_mode = { - .clock = 166666, - .hdisplay = 1200, - .hsync_start = 1200 + 28, - .hsync_end = 1200 + 28 + 10, - .htotal = 1200 + 28 + 10 + 30, - .vdisplay = 1920, - .vsync_start = 1920 + 238, - .vsync_end = 1920 + 238 + 4, - .vtotal = 1920 + 238 + 4 + 28, -}; - -static const struct drm_display_mode ws_panel_1200x1920_30fps_mode = { - .clock = 83333, - .hdisplay = 1200, - .hsync_start = 1200 + 28, - .hsync_end = 1200 + 28 + 10, - .htotal = 1200 + 28 + 10 + 30, - .vdisplay = 1920, - .vsync_start = 1920 + 238, - .vsync_end = 1920 + 238 + 4, - .vtotal = 1920 + 238 + 4 + 28, -}; - static const struct drm_display_mode ws_panel_1920x1200_60fps_mode = { .clock = 166666, .hdisplay = 1920, @@ -397,9 +372,15 @@ static const struct drm_display_mode ws_panel_1920x1200_30fps_mode = { .vtotal = 1200 + 28 + 10 + 30, }; -static const struct ws_panel_data ws_panel_automatic_data = { - .mode = NULL, - .lanes = 0, +static const struct ws_panel_data ws_panel_10_1_e_4lane_data = { + .mode = &ws_panel_1920x1200_60fps_mode, + .lanes = 4, + .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS, +}; + +static const struct ws_panel_data ws_panel_10_1_e_2lane_data = { + .mode = &ws_panel_1920x1200_30fps_mode, + .lanes = 2, .mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS, }; @@ -417,68 +398,6 @@ static void ws_panel_i2c_write(struct ws_panel *ts, u8 reg, u8 val) dev_err(&ts->i2c->dev, "I2C write failed: %d\n", ret); } -static int ws_panel_i2c_read(struct ws_panel *ts, u8 reg) -{ - int ret; - - ret = i2c_smbus_read_byte_data(ts->i2c, reg); - if (ret < 0) - dev_err(&ts->i2c->dev, "read reg 0x%02x failed %d\n", reg, ret); - return ret; -} - -static int ws_panel_auto_detect(struct ws_panel *ts) -{ - int screen_type; - int rotate; - int fps; - - fps = ws_panel_i2c_read(ts, 0xd0); - if (fps < 0) - return fps; - - rotate = ws_panel_i2c_read(ts, 0xd1); - if (rotate < 0) - return rotate; - - screen_type = ws_panel_i2c_read(ts, 0xd3); - if (screen_type < 0) - return screen_type; - - dev_info(&ts->i2c->dev, - "automatic panel detect screen_type=0x%x rotate=0x%x fps=0x%x\n", - screen_type, rotate, fps); - - if (screen_type == 0x01) { - switch (rotate) { - case 0: - case 2: - dev_info(&ts->i2c->dev, "select 1200x1920 panel\n"); - ts->mode = fps == 60 ? - &ws_panel_1200x1920_60fps_mode : - &ws_panel_1200x1920_30fps_mode; - break; - case 1: - case 3: - dev_info(&ts->i2c->dev, "select 1920x1200 panel\n"); - ts->mode = fps == 60 ? - &ws_panel_1920x1200_60fps_mode : - &ws_panel_1920x1200_30fps_mode; - break; - default: - dev_err(&ts->i2c->dev, "unknown rotate value %d\n", rotate); - return -EINVAL; - } - if (fps == 60) - ts->lanes = 4; - else - ts->lanes = 2; - return 0; - } - dev_err(&ts->i2c->dev, "unsupported panel D3=0x%x\n", screen_type); - return -EINVAL; -} - static int ws_panel_disable(struct drm_panel *panel) { struct ws_panel *ts = panel_to_ts(panel); @@ -603,6 +522,8 @@ static int ws_panel_probe(struct i2c_client *i2c) }; const struct ws_panel_data *_ws_panel_data; int ret; + bool is_10_1_e_4lane = false; + bool is_10_1_e_2lane = false; ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); if (!ts) @@ -612,24 +533,21 @@ static int ws_panel_probe(struct i2c_client *i2c) if (!_ws_panel_data) return -EINVAL; - ts->i2c = i2c; - i2c_set_clientdata(i2c, ts); - ts->lanes = _ws_panel_data->lanes; - - /* For automatic detection panels, mode is NULL - detect via I2C */ - if (!_ws_panel_data->mode) { - ret = ws_panel_auto_detect(ts); - if (ret) { - dev_err(dev, "panel auto detect failed\n"); - return ret; - } - } else { - ts->mode = _ws_panel_data->mode; - } + ts->mode = _ws_panel_data->mode; if (!ts->mode) return -EINVAL; + i2c_set_clientdata(i2c, ts); + + ts->i2c = i2c; + is_10_1_e_4lane = of_device_is_compatible(dev->of_node, + "waveshare,10.1inch-e-4lane-panel"); + is_10_1_e_2lane = of_device_is_compatible(dev->of_node, + "waveshare,10.1inch-e-2lane-panel"); + if (is_10_1_e_4lane || is_10_1_e_2lane) + ws_panel_i2c_write(ts, 0xd0, is_10_1_e_4lane ? 60 : 30); + ws_panel_i2c_write(ts, 0xc0, 0x01); ws_panel_i2c_write(ts, 0xc2, 0x01); ws_panel_i2c_write(ts, 0xac, 0x01); @@ -686,7 +604,7 @@ static int ws_panel_probe(struct i2c_client *i2c) ts->dsi->mode_flags = _ws_panel_data->mode_flags; ts->dsi->format = MIPI_DSI_FMT_RGB888; - ts->dsi->lanes = ts->lanes; + ts->dsi->lanes = _ws_panel_data->lanes; ret = devm_mipi_dsi_attach(dev, ts->dsi); @@ -775,8 +693,11 @@ static const struct of_device_id ws_panel_of_ids[] = { .compatible = "waveshare,7.0inch-h-panel", .data = &ws_panel_7_0_h_data, }, { - .compatible = "waveshare,automatic-detection-panel", - .data = &ws_panel_automatic_data, + .compatible = "waveshare,10.1inch-e-4lane-panel", + .data = &ws_panel_10_1_e_4lane_data, + }, { + .compatible = "waveshare,10.1inch-e-2lane-panel", + .data = &ws_panel_10_1_e_2lane_data, }, { /* sentinel */ }