From: Werner Johansson werner.johansson@sonymobile.com
The MIPI_DSI_TURN_ON_PERIPHERAL and MIPI_DSI_SHUTDOWN_PERIPHERAL packets are required for some panels, one example being the Panasonic VVX10F034N00 panel.
Signed-off-by: Werner Johansson werner.johansson@sonymobile.com Signed-off-by: Bjorn Andersson bjorn.andersson@sonymobile.com --- drivers/gpu/drm/drm_mipi_dsi.c | 47 ++++++++++++++++++++++++++++++++++++++++++ include/drm/drm_mipi_dsi.h | 3 +++ 2 files changed, 50 insertions(+)
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 2d5ca8ee..13b4a9c 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -862,6 +862,53 @@ int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format) } EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format);
+/** + * mipi_dsi_raw_short_write() - Sends a data-less short DSI packet + * @dsi: DSI peripheral device + * @type: Data Type of packet to send + * + * Return: 0 on success or a negative error code on failure. + */ +static ssize_t mipi_dsi_raw_short_write(struct mipi_dsi_device *dsi, u8 type) +{ + u8 dummy[2] = { 0, 0 }; + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .tx_buf = dummy, + .tx_len = sizeof(dummy), + .type = type + }; + + if (mipi_dsi_packet_format_is_short(type)) + return mipi_dsi_device_transfer(dsi, &msg); + else + return -1; +} + +/** + * mipi_dsi_turn_on_peripheral() - Sends Turn On Peripheral DSI command + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +ssize_t mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi) +{ + return mipi_dsi_raw_short_write(dsi, MIPI_DSI_TURN_ON_PERIPHERAL); +} +EXPORT_SYMBOL(mipi_dsi_turn_on_peripheral); + +/** + * mipi_dsi_shutdown_peripheral() - Sends Shutdown Peripheral DSI command + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +ssize_t mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi) +{ + return mipi_dsi_raw_short_write(dsi, MIPI_DSI_SHUTDOWN_PERIPHERAL); +} +EXPORT_SYMBOL(mipi_dsi_shutdown_peripheral); + static int mipi_dsi_drv_probe(struct device *dev) { struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver); diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index f1d8d0d..2e0f057 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h @@ -215,6 +215,9 @@ int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi, enum mipi_dsi_dcs_tear_mode mode); int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format);
+ssize_t mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi); +ssize_t mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi); + /** * struct mipi_dsi_driver - DSI driver * @driver: device driver model driver
From: Werner Johansson werner.johansson@sonymobile.com
This patch adds bindings for the Panasonic VVX10F034N00 WUXGA panel.
Signed-off-by: Werner Johansson werner.johansson@sonymobile.com Signed-off-by: Bjorn Andersson bjorn.andersson@sonymobile.com --- .../bindings/panel/panasonic,vvx10f034n00.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Documentation/devicetree/bindings/panel/panasonic,vvx10f034n00.txt
diff --git a/Documentation/devicetree/bindings/panel/panasonic,vvx10f034n00.txt b/Documentation/devicetree/bindings/panel/panasonic,vvx10f034n00.txt new file mode 100644 index 0000000..37dedf6 --- /dev/null +++ b/Documentation/devicetree/bindings/panel/panasonic,vvx10f034n00.txt @@ -0,0 +1,20 @@ +Panasonic 10" WUXGA TFT LCD panel + +Required properties: +- compatible: should be "panasonic,vvx10f034n00" +- reg: DSI virtual channel of the peripheral +- power-supply: phandle of the regulator that provides the supply voltage + +Optional properties: +- backlight: phandle of the backlight device attached to the panel + +Example: + + mdss_dsi@fd922800 { + panel@0 { + compatible = "panasonic,vvx10f034n00"; + reg = <0>; + power-supply = <&vreg_vsp>; + backlight = <&lp8566_wled>; + }; + };
On Fri, Oct 30, 2015 at 7:38 PM, bjorn@kryo.se wrote:
From: Werner Johansson werner.johansson@sonymobile.com
This patch adds bindings for the Panasonic VVX10F034N00 WUXGA panel.
Signed-off-by: Werner Johansson werner.johansson@sonymobile.com Signed-off-by: Bjorn Andersson bjorn.andersson@sonymobile.com
Acked-by: Rob Herring robh@kernel.org
.../bindings/panel/panasonic,vvx10f034n00.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Documentation/devicetree/bindings/panel/panasonic,vvx10f034n00.txt
diff --git a/Documentation/devicetree/bindings/panel/panasonic,vvx10f034n00.txt b/Documentation/devicetree/bindings/panel/panasonic,vvx10f034n00.txt new file mode 100644 index 0000000..37dedf6 --- /dev/null +++ b/Documentation/devicetree/bindings/panel/panasonic,vvx10f034n00.txt @@ -0,0 +1,20 @@ +Panasonic 10" WUXGA TFT LCD panel
+Required properties: +- compatible: should be "panasonic,vvx10f034n00" +- reg: DSI virtual channel of the peripheral +- power-supply: phandle of the regulator that provides the supply voltage
+Optional properties: +- backlight: phandle of the backlight device attached to the panel
+Example:
mdss_dsi@fd922800 {
panel@0 {
compatible = "panasonic,vvx10f034n00";
reg = <0>;
power-supply = <&vreg_vsp>;
backlight = <&lp8566_wled>;
};
};
-- 2.3.2 (Apple Git-55)
On Fri, Oct 30, 2015 at 05:38:27PM -0700, bjorn@kryo.se wrote:
From: Werner Johansson werner.johansson@sonymobile.com
This patch adds bindings for the Panasonic VVX10F034N00 WUXGA panel.
Signed-off-by: Werner Johansson werner.johansson@sonymobile.com Signed-off-by: Bjorn Andersson bjorn.andersson@sonymobile.com
.../bindings/panel/panasonic,vvx10f034n00.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Documentation/devicetree/bindings/panel/panasonic,vvx10f034n00.txt
Applied, thanks.
Thierry
From: Werner Johansson werner.johansson@sonymobile.com
This adds support for the Panasonic panel found in some Xperia Z2 tablets.
Signed-off-by: Werner Johansson werner.johansson@sonymobile.com Signed-off-by: Bjorn Andersson bjorn.andersson@sonymobile.com --- drivers/gpu/drm/panel/Kconfig | 10 + drivers/gpu/drm/panel/Makefile | 1 + .../gpu/drm/panel/panel-panasonic-vvx10f034n00.c | 334 +++++++++++++++++++++ 3 files changed, 345 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 7d4704b..77a20d6 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -51,4 +51,14 @@ config DRM_PANEL_SHARP_LQ101R1SX01 To compile this driver as a module, choose M here: the module will be called panel-sharp-lq101r1sx01.
+config DRM_PANEL_PANASONIC_VVX10F034N00 + tristate "Panasonic VVX10F034N00 1920x1200 video mode panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to enable support for Panasonic VVX10F034N00 + WUXGA (1920x1200) Novatek NT1397-based DSI panel as found in some + Xperia Z2 tablets + endmenu diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index d0f016d..a2ca8ff 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o +obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o diff --git a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c new file mode 100644 index 0000000..7f915f7 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2015 Red Hat + * Copyright (C) 2015 Sony Mobile Communications Inc. + * Author: Werner Johansson werner.johansson@sonymobile.com + * + * Based on AUO panel driver by Rob Clark robdclark@gmail.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see http://www.gnu.org/licenses/. + */ + +#include <linux/backlight.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/regulator/consumer.h> + +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_panel.h> + +#include <video/mipi_display.h> + +/* + * When power is turned off to this panel a minimum off time of 500ms has to be + * observed before powering back on as there's no external reset pin. Keep + * track of earliest wakeup time and delay subsequent prepare call accordingly + */ +#define MIN_POFF_MS (500) + +struct wuxga_nt_panel { + struct drm_panel base; + struct mipi_dsi_device *dsi; + + struct backlight_device *backlight; + struct regulator *supply; + + bool prepared; + bool enabled; + + ktime_t earliest_wake; + + const struct drm_display_mode *mode; +}; + +static inline struct wuxga_nt_panel *to_wuxga_nt_panel(struct drm_panel *panel) +{ + return container_of(panel, struct wuxga_nt_panel, base); +} + +static int wuxga_nt_panel_on(struct wuxga_nt_panel *wuxga_nt) +{ + struct mipi_dsi_device *dsi = wuxga_nt->dsi; + int ret; + + ret = mipi_dsi_turn_on_peripheral(dsi); + if (ret < 0) + return ret; + + return 0; +} + +static int wuxga_nt_panel_disable(struct drm_panel *panel) +{ + struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel); + + if (!wuxga_nt->enabled) + return 0; + + mipi_dsi_shutdown_peripheral(wuxga_nt->dsi); + + if (wuxga_nt->backlight) { + wuxga_nt->backlight->props.power = FB_BLANK_POWERDOWN; + wuxga_nt->backlight->props.state |= BL_CORE_FBBLANK; + backlight_update_status(wuxga_nt->backlight); + } + + wuxga_nt->enabled = false; + + return 0; +} + +static int wuxga_nt_panel_unprepare(struct drm_panel *panel) +{ + struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel); + + if (!wuxga_nt->prepared) + return 0; + + regulator_disable(wuxga_nt->supply); + wuxga_nt->earliest_wake = ktime_add_ms(ktime_get_real(), MIN_POFF_MS); + wuxga_nt->prepared = false; + + return 0; +} + +static int wuxga_nt_panel_prepare(struct drm_panel *panel) +{ + struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel); + int ret; + s64 enablewait; + + if (wuxga_nt->prepared) + return 0; + + /* + * If the user re-enabled the panel before the required off-time then + * we need to wait the remaining period before re-enabling regulator + */ + enablewait = ktime_ms_delta(wuxga_nt->earliest_wake, ktime_get_real()); + + /* Sanity check, this should never happen */ + if (enablewait > MIN_POFF_MS) + enablewait = MIN_POFF_MS; + + if (enablewait > 0) + msleep(enablewait); + + ret = regulator_enable(wuxga_nt->supply); + if (ret < 0) + return ret; + + /* + * A minimum delay of 250ms is required after power-up until commands + * can be sent + */ + msleep(250); + + ret = wuxga_nt_panel_on(wuxga_nt); + if (ret < 0) { + dev_err(panel->dev, "failed to set panel on: %d\n", ret); + goto poweroff; + } + + wuxga_nt->prepared = true; + + return 0; + +poweroff: + regulator_disable(wuxga_nt->supply); + + return ret; +} + +static int wuxga_nt_panel_enable(struct drm_panel *panel) +{ + struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel); + + if (wuxga_nt->enabled) + return 0; + + if (wuxga_nt->backlight) { + wuxga_nt->backlight->props.power = FB_BLANK_UNBLANK; + wuxga_nt->backlight->props.state &= ~BL_CORE_FBBLANK; + backlight_update_status(wuxga_nt->backlight); + } + + wuxga_nt->enabled = true; + + return 0; +} + +static const struct drm_display_mode default_mode = { + .clock = 164402, + .hdisplay = 1920, + .hsync_start = 1920 + 152, + .hsync_end = 1920 + 152 + 52, + .htotal = 1920 + 152 + 52 + 20, + .vdisplay = 1200, + .vsync_start = 1200 + 24, + .vsync_end = 1200 + 24 + 6, + .vtotal = 1200 + 24 + 6 + 48, + .vrefresh = 60, +}; + +static int wuxga_nt_panel_get_modes(struct drm_panel *panel) +{ + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(panel->drm, &default_mode); + if (!mode) { + dev_err(panel->drm->dev, "failed to add mode %ux%ux@%u\n", + default_mode.hdisplay, default_mode.vdisplay, + default_mode.vrefresh); + return -ENOMEM; + } + + drm_mode_set_name(mode); + + drm_mode_probed_add(panel->connector, mode); + + panel->connector->display_info.width_mm = 217; + panel->connector->display_info.height_mm = 136; + + return 1; +} + +static const struct drm_panel_funcs wuxga_nt_panel_funcs = { + .disable = wuxga_nt_panel_disable, + .unprepare = wuxga_nt_panel_unprepare, + .prepare = wuxga_nt_panel_prepare, + .enable = wuxga_nt_panel_enable, + .get_modes = wuxga_nt_panel_get_modes, +}; + +static const struct of_device_id wuxga_nt_of_match[] = { + { .compatible = "panasonic,vvx10f034n00", }, + { } +}; +MODULE_DEVICE_TABLE(of, wuxga_nt_of_match); + +static int wuxga_nt_panel_add(struct wuxga_nt_panel *wuxga_nt) +{ + struct device *dev = &wuxga_nt->dsi->dev; + struct device_node *np; + int ret; + + wuxga_nt->mode = &default_mode; + + wuxga_nt->supply = devm_regulator_get(dev, "power"); + if (IS_ERR(wuxga_nt->supply)) + return PTR_ERR(wuxga_nt->supply); + + np = of_parse_phandle(dev->of_node, "backlight", 0); + if (np) { + wuxga_nt->backlight = of_find_backlight_by_node(np); + of_node_put(np); + + if (!wuxga_nt->backlight) + return -EPROBE_DEFER; + } + + drm_panel_init(&wuxga_nt->base); + wuxga_nt->base.funcs = &wuxga_nt_panel_funcs; + wuxga_nt->base.dev = &wuxga_nt->dsi->dev; + + ret = drm_panel_add(&wuxga_nt->base); + if (ret < 0) + goto put_backlight; + + return 0; + +put_backlight: + if (wuxga_nt->backlight) + put_device(&wuxga_nt->backlight->dev); + + return ret; +} + +static void wuxga_nt_panel_del(struct wuxga_nt_panel *wuxga_nt) +{ + if (wuxga_nt->base.dev) + drm_panel_remove(&wuxga_nt->base); + + if (wuxga_nt->backlight) + put_device(&wuxga_nt->backlight->dev); +} + +static int wuxga_nt_panel_probe(struct mipi_dsi_device *dsi) +{ + struct wuxga_nt_panel *wuxga_nt; + int ret; + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | + MIPI_DSI_MODE_VIDEO_HSE | + MIPI_DSI_CLOCK_NON_CONTINUOUS | + MIPI_DSI_MODE_LPM; + + wuxga_nt = devm_kzalloc(&dsi->dev, sizeof(*wuxga_nt), GFP_KERNEL); + if (!wuxga_nt) + return -ENOMEM; + + mipi_dsi_set_drvdata(dsi, wuxga_nt); + + wuxga_nt->dsi = dsi; + + ret = wuxga_nt_panel_add(wuxga_nt); + if (ret < 0) + return ret; + + return mipi_dsi_attach(dsi); +} + +static int wuxga_nt_panel_remove(struct mipi_dsi_device *dsi) +{ + struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi); + int ret; + + ret = wuxga_nt_panel_disable(&wuxga_nt->base); + if (ret < 0) + dev_err(&dsi->dev, "failed to disable panel: %d\n", ret); + + ret = mipi_dsi_detach(dsi); + if (ret < 0) + dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); + + drm_panel_detach(&wuxga_nt->base); + wuxga_nt_panel_del(wuxga_nt); + + return 0; +} + +static void wuxga_nt_panel_shutdown(struct mipi_dsi_device *dsi) +{ + struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi); + + wuxga_nt_panel_disable(&wuxga_nt->base); +} + +static struct mipi_dsi_driver wuxga_nt_panel_driver = { + .driver = { + .name = "panel-panasonic-vvx10f034n00", + .of_match_table = wuxga_nt_of_match, + }, + .probe = wuxga_nt_panel_probe, + .remove = wuxga_nt_panel_remove, + .shutdown = wuxga_nt_panel_shutdown, +}; +module_mipi_dsi_driver(wuxga_nt_panel_driver); + +MODULE_AUTHOR("Werner Johansson werner.johansson@sonymobile.com"); +MODULE_DESCRIPTION("Panasonic VVX10F034N00 Novatek NT1397-based WUXGA (1920x1200) video mode panel driver"); +MODULE_LICENSE("GPL v2");
On Fri, Oct 30, 2015 at 5:38 PM, bjorn@kryo.se wrote:
Ping?
From: Werner Johansson werner.johansson@sonymobile.com
This adds support for the Panasonic panel found in some Xperia Z2 tablets.
Signed-off-by: Werner Johansson werner.johansson@sonymobile.com Signed-off-by: Bjorn Andersson bjorn.andersson@sonymobile.com
drivers/gpu/drm/panel/Kconfig | 10 + drivers/gpu/drm/panel/Makefile | 1 + .../gpu/drm/panel/panel-panasonic-vvx10f034n00.c | 334 +++++++++++++++++++++ 3 files changed, 345 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 7d4704b..77a20d6 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -51,4 +51,14 @@ config DRM_PANEL_SHARP_LQ101R1SX01 To compile this driver as a module, choose M here: the module will be called panel-sharp-lq101r1sx01.
+config DRM_PANEL_PANASONIC_VVX10F034N00
tristate "Panasonic VVX10F034N00 1920x1200 video mode panel"
depends on OF
depends on DRM_MIPI_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
Say Y here if you want to enable support for Panasonic VVX10F034N00
WUXGA (1920x1200) Novatek NT1397-based DSI panel as found in some
Xperia Z2 tablets
endmenu diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index d0f016d..a2ca8ff 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o +obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o diff --git a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c new file mode 100644 index 0000000..7f915f7 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c @@ -0,0 +1,334 @@ +/*
- Copyright (C) 2015 Red Hat
- Copyright (C) 2015 Sony Mobile Communications Inc.
- Author: Werner Johansson werner.johansson@sonymobile.com
- Based on AUO panel driver by Rob Clark robdclark@gmail.com
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License version 2 as published by
- the Free Software Foundation.
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- more details.
- You should have received a copy of the GNU General Public License along with
- this program. If not, see http://www.gnu.org/licenses/.
- */
+#include <linux/backlight.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/regulator/consumer.h>
+#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_panel.h>
+#include <video/mipi_display.h>
+/*
- When power is turned off to this panel a minimum off time of 500ms has to be
- observed before powering back on as there's no external reset pin. Keep
- track of earliest wakeup time and delay subsequent prepare call accordingly
- */
+#define MIN_POFF_MS (500)
+struct wuxga_nt_panel {
struct drm_panel base;
struct mipi_dsi_device *dsi;
struct backlight_device *backlight;
struct regulator *supply;
bool prepared;
bool enabled;
ktime_t earliest_wake;
const struct drm_display_mode *mode;
+};
+static inline struct wuxga_nt_panel *to_wuxga_nt_panel(struct drm_panel *panel) +{
return container_of(panel, struct wuxga_nt_panel, base);
+}
+static int wuxga_nt_panel_on(struct wuxga_nt_panel *wuxga_nt) +{
struct mipi_dsi_device *dsi = wuxga_nt->dsi;
int ret;
ret = mipi_dsi_turn_on_peripheral(dsi);
if (ret < 0)
return ret;
return 0;
+}
+static int wuxga_nt_panel_disable(struct drm_panel *panel) +{
struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
if (!wuxga_nt->enabled)
return 0;
mipi_dsi_shutdown_peripheral(wuxga_nt->dsi);
if (wuxga_nt->backlight) {
wuxga_nt->backlight->props.power = FB_BLANK_POWERDOWN;
wuxga_nt->backlight->props.state |= BL_CORE_FBBLANK;
backlight_update_status(wuxga_nt->backlight);
}
wuxga_nt->enabled = false;
return 0;
+}
+static int wuxga_nt_panel_unprepare(struct drm_panel *panel) +{
struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
if (!wuxga_nt->prepared)
return 0;
regulator_disable(wuxga_nt->supply);
wuxga_nt->earliest_wake = ktime_add_ms(ktime_get_real(), MIN_POFF_MS);
wuxga_nt->prepared = false;
return 0;
+}
+static int wuxga_nt_panel_prepare(struct drm_panel *panel) +{
struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
int ret;
s64 enablewait;
if (wuxga_nt->prepared)
return 0;
/*
* If the user re-enabled the panel before the required off-time then
* we need to wait the remaining period before re-enabling regulator
*/
enablewait = ktime_ms_delta(wuxga_nt->earliest_wake, ktime_get_real());
/* Sanity check, this should never happen */
if (enablewait > MIN_POFF_MS)
enablewait = MIN_POFF_MS;
if (enablewait > 0)
msleep(enablewait);
ret = regulator_enable(wuxga_nt->supply);
if (ret < 0)
return ret;
/*
* A minimum delay of 250ms is required after power-up until commands
* can be sent
*/
msleep(250);
ret = wuxga_nt_panel_on(wuxga_nt);
if (ret < 0) {
dev_err(panel->dev, "failed to set panel on: %d\n", ret);
goto poweroff;
}
wuxga_nt->prepared = true;
return 0;
+poweroff:
regulator_disable(wuxga_nt->supply);
return ret;
+}
+static int wuxga_nt_panel_enable(struct drm_panel *panel) +{
struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel);
if (wuxga_nt->enabled)
return 0;
if (wuxga_nt->backlight) {
wuxga_nt->backlight->props.power = FB_BLANK_UNBLANK;
wuxga_nt->backlight->props.state &= ~BL_CORE_FBBLANK;
backlight_update_status(wuxga_nt->backlight);
}
wuxga_nt->enabled = true;
return 0;
+}
+static const struct drm_display_mode default_mode = {
.clock = 164402,
.hdisplay = 1920,
.hsync_start = 1920 + 152,
.hsync_end = 1920 + 152 + 52,
.htotal = 1920 + 152 + 52 + 20,
.vdisplay = 1200,
.vsync_start = 1200 + 24,
.vsync_end = 1200 + 24 + 6,
.vtotal = 1200 + 24 + 6 + 48,
.vrefresh = 60,
+};
+static int wuxga_nt_panel_get_modes(struct drm_panel *panel) +{
struct drm_display_mode *mode;
mode = drm_mode_duplicate(panel->drm, &default_mode);
if (!mode) {
dev_err(panel->drm->dev, "failed to add mode %ux%ux@%u\n",
default_mode.hdisplay, default_mode.vdisplay,
default_mode.vrefresh);
return -ENOMEM;
}
drm_mode_set_name(mode);
drm_mode_probed_add(panel->connector, mode);
panel->connector->display_info.width_mm = 217;
panel->connector->display_info.height_mm = 136;
return 1;
+}
+static const struct drm_panel_funcs wuxga_nt_panel_funcs = {
.disable = wuxga_nt_panel_disable,
.unprepare = wuxga_nt_panel_unprepare,
.prepare = wuxga_nt_panel_prepare,
.enable = wuxga_nt_panel_enable,
.get_modes = wuxga_nt_panel_get_modes,
+};
+static const struct of_device_id wuxga_nt_of_match[] = {
{ .compatible = "panasonic,vvx10f034n00", },
{ }
+}; +MODULE_DEVICE_TABLE(of, wuxga_nt_of_match);
+static int wuxga_nt_panel_add(struct wuxga_nt_panel *wuxga_nt) +{
struct device *dev = &wuxga_nt->dsi->dev;
struct device_node *np;
int ret;
wuxga_nt->mode = &default_mode;
wuxga_nt->supply = devm_regulator_get(dev, "power");
if (IS_ERR(wuxga_nt->supply))
return PTR_ERR(wuxga_nt->supply);
np = of_parse_phandle(dev->of_node, "backlight", 0);
if (np) {
wuxga_nt->backlight = of_find_backlight_by_node(np);
of_node_put(np);
if (!wuxga_nt->backlight)
return -EPROBE_DEFER;
}
drm_panel_init(&wuxga_nt->base);
wuxga_nt->base.funcs = &wuxga_nt_panel_funcs;
wuxga_nt->base.dev = &wuxga_nt->dsi->dev;
ret = drm_panel_add(&wuxga_nt->base);
if (ret < 0)
goto put_backlight;
return 0;
+put_backlight:
if (wuxga_nt->backlight)
put_device(&wuxga_nt->backlight->dev);
return ret;
+}
+static void wuxga_nt_panel_del(struct wuxga_nt_panel *wuxga_nt) +{
if (wuxga_nt->base.dev)
drm_panel_remove(&wuxga_nt->base);
if (wuxga_nt->backlight)
put_device(&wuxga_nt->backlight->dev);
+}
+static int wuxga_nt_panel_probe(struct mipi_dsi_device *dsi) +{
struct wuxga_nt_panel *wuxga_nt;
int ret;
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
MIPI_DSI_MODE_VIDEO_HSE |
MIPI_DSI_CLOCK_NON_CONTINUOUS |
MIPI_DSI_MODE_LPM;
wuxga_nt = devm_kzalloc(&dsi->dev, sizeof(*wuxga_nt), GFP_KERNEL);
if (!wuxga_nt)
return -ENOMEM;
mipi_dsi_set_drvdata(dsi, wuxga_nt);
wuxga_nt->dsi = dsi;
ret = wuxga_nt_panel_add(wuxga_nt);
if (ret < 0)
return ret;
return mipi_dsi_attach(dsi);
+}
+static int wuxga_nt_panel_remove(struct mipi_dsi_device *dsi) +{
struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi);
int ret;
ret = wuxga_nt_panel_disable(&wuxga_nt->base);
if (ret < 0)
dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
ret = mipi_dsi_detach(dsi);
if (ret < 0)
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
drm_panel_detach(&wuxga_nt->base);
wuxga_nt_panel_del(wuxga_nt);
return 0;
+}
+static void wuxga_nt_panel_shutdown(struct mipi_dsi_device *dsi) +{
struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi);
wuxga_nt_panel_disable(&wuxga_nt->base);
+}
+static struct mipi_dsi_driver wuxga_nt_panel_driver = {
.driver = {
.name = "panel-panasonic-vvx10f034n00",
.of_match_table = wuxga_nt_of_match,
},
.probe = wuxga_nt_panel_probe,
.remove = wuxga_nt_panel_remove,
.shutdown = wuxga_nt_panel_shutdown,
+}; +module_mipi_dsi_driver(wuxga_nt_panel_driver);
+MODULE_AUTHOR("Werner Johansson werner.johansson@sonymobile.com"); +MODULE_DESCRIPTION("Panasonic VVX10F034N00 Novatek NT1397-based WUXGA (1920x1200) video mode panel driver");
+MODULE_LICENSE("GPL v2");
2.3.2 (Apple Git-55)
On Fri, Oct 30, 2015 at 05:38:28PM -0700, bjorn@kryo.se wrote:
From: Werner Johansson werner.johansson@sonymobile.com
This adds support for the Panasonic panel found in some Xperia Z2 tablets.
Signed-off-by: Werner Johansson werner.johansson@sonymobile.com Signed-off-by: Bjorn Andersson bjorn.andersson@sonymobile.com
drivers/gpu/drm/panel/Kconfig | 10 + drivers/gpu/drm/panel/Makefile | 1 + .../gpu/drm/panel/panel-panasonic-vvx10f034n00.c | 334 +++++++++++++++++++++ 3 files changed, 345 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
Applied, though I had to reorder Makefile and Kconfig entries to keep alphabetic ordering.
Thanks, Thierry
On Mon, Nov 23, 2015 at 3:33 AM, Thierry Reding thierry.reding@gmail.com wrote:
On Fri, Oct 30, 2015 at 05:38:28PM -0700, bjorn@kryo.se wrote:
From: Werner Johansson werner.johansson@sonymobile.com
This adds support for the Panasonic panel found in some Xperia Z2 tablets.
Signed-off-by: Werner Johansson werner.johansson@sonymobile.com Signed-off-by: Bjorn Andersson bjorn.andersson@sonymobile.com
drivers/gpu/drm/panel/Kconfig | 10 + drivers/gpu/drm/panel/Makefile | 1 + .../gpu/drm/panel/panel-panasonic-vvx10f034n00.c | 334 +++++++++++++++++++++ 3 files changed, 345 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
Applied, though I had to reorder Makefile and Kconfig entries to keep alphabetic ordering.
Thanks, now we're close to play Quake3 on the mainline kernel on the Xperia Z2 Tablet :)
Did you pull patch 1/3 from this set as well? I didn't get a reply on it and wanted to check as this patch (3/3) has a build dependency on it.
Patch 1/3: https://patchwork.kernel.org/patch/7530121/
Regards, Bjorn
On Fri, Oct 30, 2015 at 5:38 PM, bjorn@kryo.se wrote:
Ping?
From: Werner Johansson werner.johansson@sonymobile.com
The MIPI_DSI_TURN_ON_PERIPHERAL and MIPI_DSI_SHUTDOWN_PERIPHERAL packets are required for some panels, one example being the Panasonic VVX10F034N00 panel.
Signed-off-by: Werner Johansson werner.johansson@sonymobile.com Signed-off-by: Bjorn Andersson bjorn.andersson@sonymobile.com
drivers/gpu/drm/drm_mipi_dsi.c | 47 ++++++++++++++++++++++++++++++++++++++++++ include/drm/drm_mipi_dsi.h | 3 +++ 2 files changed, 50 insertions(+)
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 2d5ca8ee..13b4a9c 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -862,6 +862,53 @@ int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format) } EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format);
+/**
- mipi_dsi_raw_short_write() - Sends a data-less short DSI packet
- @dsi: DSI peripheral device
- @type: Data Type of packet to send
- Return: 0 on success or a negative error code on failure.
- */
+static ssize_t mipi_dsi_raw_short_write(struct mipi_dsi_device *dsi, u8 type) +{
u8 dummy[2] = { 0, 0 };
struct mipi_dsi_msg msg = {
.channel = dsi->channel,
.tx_buf = dummy,
.tx_len = sizeof(dummy),
.type = type
};
if (mipi_dsi_packet_format_is_short(type))
return mipi_dsi_device_transfer(dsi, &msg);
else
return -1;
+}
+/**
- mipi_dsi_turn_on_peripheral() - Sends Turn On Peripheral DSI command
- @dsi: DSI peripheral device
- Return: 0 on success or a negative error code on failure.
- */
+ssize_t mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi) +{
return mipi_dsi_raw_short_write(dsi, MIPI_DSI_TURN_ON_PERIPHERAL);
+} +EXPORT_SYMBOL(mipi_dsi_turn_on_peripheral);
+/**
- mipi_dsi_shutdown_peripheral() - Sends Shutdown Peripheral DSI command
- @dsi: DSI peripheral device
- Return: 0 on success or a negative error code on failure.
- */
+ssize_t mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi) +{
return mipi_dsi_raw_short_write(dsi, MIPI_DSI_SHUTDOWN_PERIPHERAL);
+} +EXPORT_SYMBOL(mipi_dsi_shutdown_peripheral);
static int mipi_dsi_drv_probe(struct device *dev) { struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver); diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index f1d8d0d..2e0f057 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h @@ -215,6 +215,9 @@ int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi, enum mipi_dsi_dcs_tear_mode mode); int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format);
+ssize_t mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi); +ssize_t mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi);
/**
- struct mipi_dsi_driver - DSI driver
- @driver: device driver model driver
-- 2.3.2 (Apple Git-55)
On Fri, Oct 30, 2015 at 05:38:26PM -0700, bjorn@kryo.se wrote:
From: Werner Johansson werner.johansson@sonymobile.com
The MIPI_DSI_TURN_ON_PERIPHERAL and MIPI_DSI_SHUTDOWN_PERIPHERAL packets are required for some panels, one example being the Panasonic VVX10F034N00 panel.
Signed-off-by: Werner Johansson werner.johansson@sonymobile.com Signed-off-by: Bjorn Andersson bjorn.andersson@sonymobile.com
drivers/gpu/drm/drm_mipi_dsi.c | 47 ++++++++++++++++++++++++++++++++++++++++++ include/drm/drm_mipi_dsi.h | 3 +++ 2 files changed, 50 insertions(+)
This being a dependency on 3/3 it would've been good to send this To: me as well. I hadn't seen this in my inbox and had simply discarded it as being independent. Of course if I had properly checked the build I would've noticed...
Anyway, I've applied this with slight modifications. I removed the raw short write helper. I don't think it buys us much and we already have an open-coded variant in mipi_dsi_set_maximum_return_packet_size(). I've also moved these functions closer to the Set Maximum Return Packet Size command implementation because they are part of the same command set. I also made the functions return int instead of ssize_t to avoid potential confusion about their return value (ssize_t implies "number of bytes transferred, or a negative error code on failure).
One minor comment below...
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 2d5ca8ee..13b4a9c 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -862,6 +862,53 @@ int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format) } EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format);
+/**
- mipi_dsi_raw_short_write() - Sends a data-less short DSI packet
- @dsi: DSI peripheral device
- @type: Data Type of packet to send
- Return: 0 on success or a negative error code on failure.
- */
+static ssize_t mipi_dsi_raw_short_write(struct mipi_dsi_device *dsi, u8 type) +{
- u8 dummy[2] = { 0, 0 };
- struct mipi_dsi_msg msg = {
.channel = dsi->channel,
.tx_buf = dummy,
.tx_len = sizeof(dummy),
.type = type
- };
- if (mipi_dsi_packet_format_is_short(type))
return mipi_dsi_device_transfer(dsi, &msg);
- else
return -1;
+}
When the kerneldoc comment says "negative error code", developers will expect one of the -E* constants. -1 maps to -EPERM (operation not permitted), which isn't a good error code for this case. This is also an internal function, so these errors really should never happen.
Anyway, since I removed this helper this isn't an issue anymore, just wanted to mention it.
Thanks, Thierry
On Tue, Nov 24, 2015 at 1:33 AM, Thierry Reding thierry.reding@gmail.com wrote:
On Fri, Oct 30, 2015 at 05:38:26PM -0700, bjorn@kryo.se wrote:
From: Werner Johansson werner.johansson@sonymobile.com
The MIPI_DSI_TURN_ON_PERIPHERAL and MIPI_DSI_SHUTDOWN_PERIPHERAL packets are required for some panels, one example being the Panasonic VVX10F034N00 panel.
Signed-off-by: Werner Johansson werner.johansson@sonymobile.com Signed-off-by: Bjorn Andersson bjorn.andersson@sonymobile.com
drivers/gpu/drm/drm_mipi_dsi.c | 47 ++++++++++++++++++++++++++++++++++++++++++ include/drm/drm_mipi_dsi.h | 3 +++ 2 files changed, 50 insertions(+)
This being a dependency on 3/3 it would've been good to send this To: me as well. I hadn't seen this in my inbox and had simply discarded it as being independent. Of course if I had properly checked the build I would've noticed...
Sorry for not including you as a recipient, I relied too heavily on get_maintainer. Thanks for fixing my misstake.
Anyway, I've applied this with slight modifications. I removed the raw short write helper. I don't think it buys us much and we already have an open-coded variant in mipi_dsi_set_maximum_return_packet_size(). I've also moved these functions closer to the Set Maximum Return Packet Size command implementation because they are part of the same command set. I also made the functions return int instead of ssize_t to avoid potential confusion about their return value (ssize_t implies "number of bytes transferred, or a negative error code on failure).
Sounds good, thanks.
One minor comment below...
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 2d5ca8ee..13b4a9c 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -862,6 +862,53 @@ int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format) } EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format);
+/**
- mipi_dsi_raw_short_write() - Sends a data-less short DSI packet
- @dsi: DSI peripheral device
- @type: Data Type of packet to send
- Return: 0 on success or a negative error code on failure.
- */
+static ssize_t mipi_dsi_raw_short_write(struct mipi_dsi_device *dsi, u8 type) +{
u8 dummy[2] = { 0, 0 };
struct mipi_dsi_msg msg = {
.channel = dsi->channel,
.tx_buf = dummy,
.tx_len = sizeof(dummy),
.type = type
};
if (mipi_dsi_packet_format_is_short(type))
return mipi_dsi_device_transfer(dsi, &msg);
else
return -1;
+}
When the kerneldoc comment says "negative error code", developers will expect one of the -E* constants. -1 maps to -EPERM (operation not permitted), which isn't a good error code for this case. This is also an internal function, so these errors really should never happen.
Anyway, since I removed this helper this isn't an issue anymore, just wanted to mention it.
Right. Thanks for fixing it!
Regards, Bjorn
dri-devel@lists.freedesktop.org