diff options
author | Dave Airlie <airlied@redhat.com> | 2015-12-16 17:37:52 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2015-12-16 17:37:52 -0500 |
commit | 07ade8446192296fa7149a035c1d2e14341fbc22 (patch) | |
tree | efaa14f48cfc0b4da214db8df89392478e4642bb | |
parent | 51bce5bc38bdb79c0f7ab33f1fe91a68ef1afa77 (diff) | |
parent | d2a6f0f5597696ebf5bb34089be3b88ba2455b7a (diff) |
Merge tag 'drm/panel/for-4.5-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next
drm/panel: Changes for v4.5-rc1
This set of changes brings in a few more helpers for DSI support as well
as a couple of new drivers and support for some more simple panels.
* tag 'drm/panel/for-4.5-rc1' of git://anongit.freedesktop.org/tegra/linux:
drm/panel: simple: Add QiaoDian qd43003c0-40
of: Add vendor prefix for QiaoDian Xianshi
drm/panel: add kernel doc for size attributes in panel_desc
drm/panel: simple: Add support for Kyocera TCG121XGLP panel
devicetree: add vendor prefix for Kyocera Corporation
drm/bridge: Remove gratuitous blank line
drm/bridge: dw-hdmi: Use dashes in filenames
drm/panel: Add Sharp LS043T1LE01 MIPI DSI panel
dt-bindings: Add Sharp LS043T1LE01 panel binding
drm/dsi: Add Turn On/Shutdown Peripheral command helpers
drm/panel: Add Panasonic VVX10F034N00 MIPI DSI panel
dt-bindings: Add Panasonic VVX10F034N00 panel binding
drm/panel: simple: Add support for Innolux G121X1-L03
drm/panel: simple: Add support for BOE TV080WUM-NL0
dt-bindings: Add BOE TV080WUM-NL0 panel binding
of: Add vendor prefix for BOE Technology Group
drm/dsi: Add a helper to get bits per pixel of MIPI DSI pixel format
20 files changed, 1008 insertions, 6 deletions
diff --git a/Documentation/devicetree/bindings/display/panel/boe,tv080wum-nl0.txt b/Documentation/devicetree/bindings/display/panel/boe,tv080wum-nl0.txt new file mode 100644 index 000000000000..50be5e2438b2 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/boe,tv080wum-nl0.txt | |||
@@ -0,0 +1,7 @@ | |||
1 | Boe Corporation 8.0" WUXGA TFT LCD panel | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: should be "boe,tv080wum-nl0" | ||
5 | |||
6 | This binding is compatible with the simple-panel binding, which is specified | ||
7 | in simple-panel.txt in this directory. | ||
diff --git a/Documentation/devicetree/bindings/display/panel/innolux,g121x1-l03.txt b/Documentation/devicetree/bindings/display/panel/innolux,g121x1-l03.txt new file mode 100644 index 000000000000..649744620ae1 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/innolux,g121x1-l03.txt | |||
@@ -0,0 +1,7 @@ | |||
1 | Innolux Corporation 12.1" G121X1-L03 XGA (1024x768) TFT LCD panel | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: should be "innolux,g121x1-l03" | ||
5 | |||
6 | This binding is compatible with the simple-panel binding, which is specified | ||
7 | in simple-panel.txt in this directory. | ||
diff --git a/Documentation/devicetree/bindings/display/panel/kyo,tcg121xglp.txt b/Documentation/devicetree/bindings/display/panel/kyo,tcg121xglp.txt new file mode 100644 index 000000000000..a8e940fe731e --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/kyo,tcg121xglp.txt | |||
@@ -0,0 +1,7 @@ | |||
1 | Kyocera Corporation 12.1" XGA (1024x768) TFT LCD panel | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: should be "kyo,tcg121xglp" | ||
5 | |||
6 | This binding is compatible with the simple-panel binding, which is specified | ||
7 | in simple-panel.txt in this directory. | ||
diff --git a/Documentation/devicetree/bindings/display/panel/sharp,ls043t1le01.txt b/Documentation/devicetree/bindings/display/panel/sharp,ls043t1le01.txt new file mode 100644 index 000000000000..3770a111968b --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/sharp,ls043t1le01.txt | |||
@@ -0,0 +1,22 @@ | |||
1 | Sharp Microelectronics 4.3" qHD TFT LCD panel | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: should be "sharp,ls043t1le01-qhd" | ||
5 | - reg: DSI virtual channel of the peripheral | ||
6 | - power-supply: phandle of the regulator that provides the supply voltage | ||
7 | |||
8 | Optional properties: | ||
9 | - backlight: phandle of the backlight device attached to the panel | ||
10 | - reset-gpios: a GPIO spec for the reset pin | ||
11 | |||
12 | Example: | ||
13 | |||
14 | mdss_dsi@fd922800 { | ||
15 | panel@0 { | ||
16 | compatible = "sharp,ls043t1le01-qhd"; | ||
17 | reg = <0>; | ||
18 | avdd-supply = <&pm8941_l22>; | ||
19 | backlight = <&pm8941_wled>; | ||
20 | reset-gpios = <&pm8941_gpios 19 GPIO_ACTIVE_HIGH>; | ||
21 | }; | ||
22 | }; | ||
diff --git a/Documentation/devicetree/bindings/panel/panasonic,vvx10f034n00.txt b/Documentation/devicetree/bindings/panel/panasonic,vvx10f034n00.txt new file mode 100644 index 000000000000..37dedf6a6702 --- /dev/null +++ b/Documentation/devicetree/bindings/panel/panasonic,vvx10f034n00.txt | |||
@@ -0,0 +1,20 @@ | |||
1 | Panasonic 10" WUXGA TFT LCD panel | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: should be "panasonic,vvx10f034n00" | ||
5 | - reg: DSI virtual channel of the peripheral | ||
6 | - power-supply: phandle of the regulator that provides the supply voltage | ||
7 | |||
8 | Optional properties: | ||
9 | - backlight: phandle of the backlight device attached to the panel | ||
10 | |||
11 | Example: | ||
12 | |||
13 | mdss_dsi@fd922800 { | ||
14 | panel@0 { | ||
15 | compatible = "panasonic,vvx10f034n00"; | ||
16 | reg = <0>; | ||
17 | power-supply = <&vreg_vsp>; | ||
18 | backlight = <&lp8566_wled>; | ||
19 | }; | ||
20 | }; | ||
diff --git a/Documentation/devicetree/bindings/panel/qiaodian,qd43003c0-40.txt b/Documentation/devicetree/bindings/panel/qiaodian,qd43003c0-40.txt new file mode 100644 index 000000000000..0fbdab89ac3d --- /dev/null +++ b/Documentation/devicetree/bindings/panel/qiaodian,qd43003c0-40.txt | |||
@@ -0,0 +1,7 @@ | |||
1 | QiaoDian XianShi Corporation 4"3 TFT LCD panel | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: should be "qiaodian,qd43003c0-40" | ||
5 | |||
6 | This binding is compatible with the simple-panel binding, which is specified | ||
7 | in simple-panel.txt in this directory. | ||
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 55df1d444e9f..6b0fc4ff3c47 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt | |||
@@ -33,6 +33,7 @@ auo AU Optronics Corporation | |||
33 | avago Avago Technologies | 33 | avago Avago Technologies |
34 | avic Shanghai AVIC Optoelectronics Co., Ltd. | 34 | avic Shanghai AVIC Optoelectronics Co., Ltd. |
35 | axis Axis Communications AB | 35 | axis Axis Communications AB |
36 | boe BOE Technology Group Co., Ltd. | ||
36 | bosch Bosch Sensortec GmbH | 37 | bosch Bosch Sensortec GmbH |
37 | boundary Boundary Devices Inc. | 38 | boundary Boundary Devices Inc. |
38 | brcm Broadcom Corporation | 39 | brcm Broadcom Corporation |
@@ -123,6 +124,7 @@ jedec JEDEC Solid State Technology Association | |||
123 | karo Ka-Ro electronics GmbH | 124 | karo Ka-Ro electronics GmbH |
124 | keymile Keymile GmbH | 125 | keymile Keymile GmbH |
125 | kinetic Kinetic Technologies | 126 | kinetic Kinetic Technologies |
127 | kyo Kyocera Corporation | ||
126 | lacie LaCie | 128 | lacie LaCie |
127 | lantiq Lantiq Semiconductor | 129 | lantiq Lantiq Semiconductor |
128 | lenovo Lenovo Group Ltd. | 130 | lenovo Lenovo Group Ltd. |
@@ -180,6 +182,7 @@ qca Qualcomm Atheros, Inc. | |||
180 | qcom Qualcomm Technologies, Inc | 182 | qcom Qualcomm Technologies, Inc |
181 | qemu QEMU, a generic and open source machine emulator and virtualizer | 183 | qemu QEMU, a generic and open source machine emulator and virtualizer |
182 | qi Qi Hardware | 184 | qi Qi Hardware |
185 | qiaodian QiaoDian XianShi Corporation | ||
183 | qnap QNAP Systems, Inc. | 186 | qnap QNAP Systems, Inc. |
184 | radxa Radxa | 187 | radxa Radxa |
185 | raidsonic RaidSonic Technology GmbH | 188 | raidsonic RaidSonic Technology GmbH |
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 6dddd392aa42..27e2022de89d 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig | |||
@@ -22,7 +22,6 @@ config DRM_DW_HDMI_AHB_AUDIO | |||
22 | Designware HDMI block. This is used in conjunction with | 22 | Designware HDMI block. This is used in conjunction with |
23 | the i.MX6 HDMI driver. | 23 | the i.MX6 HDMI driver. |
24 | 24 | ||
25 | |||
26 | config DRM_NXP_PTN3460 | 25 | config DRM_NXP_PTN3460 |
27 | tristate "NXP PTN3460 DP/LVDS bridge" | 26 | tristate "NXP PTN3460 DP/LVDS bridge" |
28 | depends on OF | 27 | depends on OF |
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index d4e28beec30e..f13c33d67c03 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | ccflags-y := -Iinclude/drm | 1 | ccflags-y := -Iinclude/drm |
2 | 2 | ||
3 | obj-$(CONFIG_DRM_DW_HDMI) += dw_hdmi.o | 3 | obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o |
4 | obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw_hdmi-ahb-audio.o | 4 | obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o |
5 | obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o | 5 | obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o |
6 | obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o | 6 | obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o |
diff --git a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c index 59f630f1c61a..122bb015f4a9 100644 --- a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c +++ b/drivers/gpu/drm/bridge/dw-hdmi-ahb-audio.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <sound/pcm_drm_eld.h> | 21 | #include <sound/pcm_drm_eld.h> |
22 | #include <sound/pcm_iec958.h> | 22 | #include <sound/pcm_iec958.h> |
23 | 23 | ||
24 | #include "dw_hdmi-audio.h" | 24 | #include "dw-hdmi-audio.h" |
25 | 25 | ||
26 | #define DRIVER_NAME "dw-hdmi-ahb-audio" | 26 | #define DRIVER_NAME "dw-hdmi-ahb-audio" |
27 | 27 | ||
diff --git a/drivers/gpu/drm/bridge/dw_hdmi-audio.h b/drivers/gpu/drm/bridge/dw-hdmi-audio.h index 91f631beecc7..91f631beecc7 100644 --- a/drivers/gpu/drm/bridge/dw_hdmi-audio.h +++ b/drivers/gpu/drm/bridge/dw-hdmi-audio.h | |||
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c index 56de9f1c95fc..298018a8562e 100644 --- a/drivers/gpu/drm/bridge/dw_hdmi.c +++ b/drivers/gpu/drm/bridge/dw-hdmi.c | |||
@@ -27,8 +27,8 @@ | |||
27 | #include <drm/drm_encoder_slave.h> | 27 | #include <drm/drm_encoder_slave.h> |
28 | #include <drm/bridge/dw_hdmi.h> | 28 | #include <drm/bridge/dw_hdmi.h> |
29 | 29 | ||
30 | #include "dw_hdmi.h" | 30 | #include "dw-hdmi.h" |
31 | #include "dw_hdmi-audio.h" | 31 | #include "dw-hdmi-audio.h" |
32 | 32 | ||
33 | #define HDMI_EDID_LEN 512 | 33 | #define HDMI_EDID_LEN 512 |
34 | 34 | ||
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.h b/drivers/gpu/drm/bridge/dw-hdmi.h index fc9a560429d6..fc9a560429d6 100644 --- a/drivers/gpu/drm/bridge/dw_hdmi.h +++ b/drivers/gpu/drm/bridge/dw-hdmi.h | |||
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 2d5ca8eec13a..6e6a9c58d404 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c | |||
@@ -365,6 +365,44 @@ int mipi_dsi_create_packet(struct mipi_dsi_packet *packet, | |||
365 | } | 365 | } |
366 | EXPORT_SYMBOL(mipi_dsi_create_packet); | 366 | EXPORT_SYMBOL(mipi_dsi_create_packet); |
367 | 367 | ||
368 | /** | ||
369 | * mipi_dsi_shutdown_peripheral() - sends a Shutdown Peripheral command | ||
370 | * @dsi: DSI peripheral device | ||
371 | * | ||
372 | * Return: 0 on success or a negative error code on failure. | ||
373 | */ | ||
374 | int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi) | ||
375 | { | ||
376 | struct mipi_dsi_msg msg = { | ||
377 | .channel = dsi->channel, | ||
378 | .type = MIPI_DSI_SHUTDOWN_PERIPHERAL, | ||
379 | .tx_buf = (u8 [2]) { 0, 0 }, | ||
380 | .tx_len = 2, | ||
381 | }; | ||
382 | |||
383 | return mipi_dsi_device_transfer(dsi, &msg); | ||
384 | } | ||
385 | EXPORT_SYMBOL(mipi_dsi_shutdown_peripheral); | ||
386 | |||
387 | /** | ||
388 | * mipi_dsi_turn_on_peripheral() - sends a Turn On Peripheral command | ||
389 | * @dsi: DSI peripheral device | ||
390 | * | ||
391 | * Return: 0 on success or a negative error code on failure. | ||
392 | */ | ||
393 | int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi) | ||
394 | { | ||
395 | struct mipi_dsi_msg msg = { | ||
396 | .channel = dsi->channel, | ||
397 | .type = MIPI_DSI_TURN_ON_PERIPHERAL, | ||
398 | .tx_buf = (u8 [2]) { 0, 0 }, | ||
399 | .tx_len = 2, | ||
400 | }; | ||
401 | |||
402 | return mipi_dsi_device_transfer(dsi, &msg); | ||
403 | } | ||
404 | EXPORT_SYMBOL(mipi_dsi_turn_on_peripheral); | ||
405 | |||
368 | /* | 406 | /* |
369 | * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of the | 407 | * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of the |
370 | * the payload in a long packet transmitted from the peripheral back to the | 408 | * the payload in a long packet transmitted from the peripheral back to the |
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 7d4704b1292b..1500ab99f548 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig | |||
@@ -31,6 +31,16 @@ config DRM_PANEL_LG_LG4573 | |||
31 | Say Y here if you want to enable support for LG4573 RGB panel. | 31 | Say Y here if you want to enable support for LG4573 RGB panel. |
32 | To compile this driver as a module, choose M here. | 32 | To compile this driver as a module, choose M here. |
33 | 33 | ||
34 | config DRM_PANEL_PANASONIC_VVX10F034N00 | ||
35 | tristate "Panasonic VVX10F034N00 1920x1200 video mode panel" | ||
36 | depends on OF | ||
37 | depends on DRM_MIPI_DSI | ||
38 | depends on BACKLIGHT_CLASS_DEVICE | ||
39 | help | ||
40 | Say Y here if you want to enable support for Panasonic VVX10F034N00 | ||
41 | WUXGA (1920x1200) Novatek NT1397-based DSI panel as found in some | ||
42 | Xperia Z2 tablets | ||
43 | |||
34 | config DRM_PANEL_SAMSUNG_S6E8AA0 | 44 | config DRM_PANEL_SAMSUNG_S6E8AA0 |
35 | tristate "Samsung S6E8AA0 DSI video mode panel" | 45 | tristate "Samsung S6E8AA0 DSI video mode panel" |
36 | depends on OF | 46 | depends on OF |
@@ -51,4 +61,13 @@ config DRM_PANEL_SHARP_LQ101R1SX01 | |||
51 | To compile this driver as a module, choose M here: the module | 61 | To compile this driver as a module, choose M here: the module |
52 | will be called panel-sharp-lq101r1sx01. | 62 | will be called panel-sharp-lq101r1sx01. |
53 | 63 | ||
64 | config DRM_PANEL_SHARP_LS043T1LE01 | ||
65 | tristate "Sharp LS043T1LE01 qHD video mode panel" | ||
66 | depends on OF | ||
67 | depends on DRM_MIPI_DSI | ||
68 | depends on BACKLIGHT_CLASS_DEVICE | ||
69 | help | ||
70 | Say Y here if you want to enable support for Sharp LS043T1LE01 qHD | ||
71 | (540x960) DSI panel as found on the Qualcomm APQ8074 Dragonboard | ||
72 | |||
54 | endmenu | 73 | endmenu |
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index d0f016dd7ddb..f277eed933d6 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile | |||
@@ -1,5 +1,7 @@ | |||
1 | obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o | 1 | obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o |
2 | obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o | 2 | obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o |
3 | obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o | ||
3 | obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o | 4 | obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o |
4 | obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o | 5 | obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o |
5 | obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o | 6 | obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o |
7 | obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.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 000000000000..7f915f706fa6 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c | |||
@@ -0,0 +1,334 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Red Hat | ||
3 | * Copyright (C) 2015 Sony Mobile Communications Inc. | ||
4 | * Author: Werner Johansson <werner.johansson@sonymobile.com> | ||
5 | * | ||
6 | * Based on AUO panel driver by Rob Clark <robdclark@gmail.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License version 2 as published by | ||
10 | * the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include <linux/backlight.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/regulator/consumer.h> | ||
25 | |||
26 | #include <drm/drmP.h> | ||
27 | #include <drm/drm_crtc.h> | ||
28 | #include <drm/drm_mipi_dsi.h> | ||
29 | #include <drm/drm_panel.h> | ||
30 | |||
31 | #include <video/mipi_display.h> | ||
32 | |||
33 | /* | ||
34 | * When power is turned off to this panel a minimum off time of 500ms has to be | ||
35 | * observed before powering back on as there's no external reset pin. Keep | ||
36 | * track of earliest wakeup time and delay subsequent prepare call accordingly | ||
37 | */ | ||
38 | #define MIN_POFF_MS (500) | ||
39 | |||
40 | struct wuxga_nt_panel { | ||
41 | struct drm_panel base; | ||
42 | struct mipi_dsi_device *dsi; | ||
43 | |||
44 | struct backlight_device *backlight; | ||
45 | struct regulator *supply; | ||
46 | |||
47 | bool prepared; | ||
48 | bool enabled; | ||
49 | |||
50 | ktime_t earliest_wake; | ||
51 | |||
52 | const struct drm_display_mode *mode; | ||
53 | }; | ||
54 | |||
55 | static inline struct wuxga_nt_panel *to_wuxga_nt_panel(struct drm_panel *panel) | ||
56 | { | ||
57 | return container_of(panel, struct wuxga_nt_panel, base); | ||
58 | } | ||
59 | |||
60 | static int wuxga_nt_panel_on(struct wuxga_nt_panel *wuxga_nt) | ||
61 | { | ||
62 | struct mipi_dsi_device *dsi = wuxga_nt->dsi; | ||
63 | int ret; | ||
64 | |||
65 | ret = mipi_dsi_turn_on_peripheral(dsi); | ||
66 | if (ret < 0) | ||
67 | return ret; | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static int wuxga_nt_panel_disable(struct drm_panel *panel) | ||
73 | { | ||
74 | struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel); | ||
75 | |||
76 | if (!wuxga_nt->enabled) | ||
77 | return 0; | ||
78 | |||
79 | mipi_dsi_shutdown_peripheral(wuxga_nt->dsi); | ||
80 | |||
81 | if (wuxga_nt->backlight) { | ||
82 | wuxga_nt->backlight->props.power = FB_BLANK_POWERDOWN; | ||
83 | wuxga_nt->backlight->props.state |= BL_CORE_FBBLANK; | ||
84 | backlight_update_status(wuxga_nt->backlight); | ||
85 | } | ||
86 | |||
87 | wuxga_nt->enabled = false; | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static int wuxga_nt_panel_unprepare(struct drm_panel *panel) | ||
93 | { | ||
94 | struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel); | ||
95 | |||
96 | if (!wuxga_nt->prepared) | ||
97 | return 0; | ||
98 | |||
99 | regulator_disable(wuxga_nt->supply); | ||
100 | wuxga_nt->earliest_wake = ktime_add_ms(ktime_get_real(), MIN_POFF_MS); | ||
101 | wuxga_nt->prepared = false; | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int wuxga_nt_panel_prepare(struct drm_panel *panel) | ||
107 | { | ||
108 | struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel); | ||
109 | int ret; | ||
110 | s64 enablewait; | ||
111 | |||
112 | if (wuxga_nt->prepared) | ||
113 | return 0; | ||
114 | |||
115 | /* | ||
116 | * If the user re-enabled the panel before the required off-time then | ||
117 | * we need to wait the remaining period before re-enabling regulator | ||
118 | */ | ||
119 | enablewait = ktime_ms_delta(wuxga_nt->earliest_wake, ktime_get_real()); | ||
120 | |||
121 | /* Sanity check, this should never happen */ | ||
122 | if (enablewait > MIN_POFF_MS) | ||
123 | enablewait = MIN_POFF_MS; | ||
124 | |||
125 | if (enablewait > 0) | ||
126 | msleep(enablewait); | ||
127 | |||
128 | ret = regulator_enable(wuxga_nt->supply); | ||
129 | if (ret < 0) | ||
130 | return ret; | ||
131 | |||
132 | /* | ||
133 | * A minimum delay of 250ms is required after power-up until commands | ||
134 | * can be sent | ||
135 | */ | ||
136 | msleep(250); | ||
137 | |||
138 | ret = wuxga_nt_panel_on(wuxga_nt); | ||
139 | if (ret < 0) { | ||
140 | dev_err(panel->dev, "failed to set panel on: %d\n", ret); | ||
141 | goto poweroff; | ||
142 | } | ||
143 | |||
144 | wuxga_nt->prepared = true; | ||
145 | |||
146 | return 0; | ||
147 | |||
148 | poweroff: | ||
149 | regulator_disable(wuxga_nt->supply); | ||
150 | |||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | static int wuxga_nt_panel_enable(struct drm_panel *panel) | ||
155 | { | ||
156 | struct wuxga_nt_panel *wuxga_nt = to_wuxga_nt_panel(panel); | ||
157 | |||
158 | if (wuxga_nt->enabled) | ||
159 | return 0; | ||
160 | |||
161 | if (wuxga_nt->backlight) { | ||
162 | wuxga_nt->backlight->props.power = FB_BLANK_UNBLANK; | ||
163 | wuxga_nt->backlight->props.state &= ~BL_CORE_FBBLANK; | ||
164 | backlight_update_status(wuxga_nt->backlight); | ||
165 | } | ||
166 | |||
167 | wuxga_nt->enabled = true; | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static const struct drm_display_mode default_mode = { | ||
173 | .clock = 164402, | ||
174 | .hdisplay = 1920, | ||
175 | .hsync_start = 1920 + 152, | ||
176 | .hsync_end = 1920 + 152 + 52, | ||
177 | .htotal = 1920 + 152 + 52 + 20, | ||
178 | .vdisplay = 1200, | ||
179 | .vsync_start = 1200 + 24, | ||
180 | .vsync_end = 1200 + 24 + 6, | ||
181 | .vtotal = 1200 + 24 + 6 + 48, | ||
182 | .vrefresh = 60, | ||
183 | }; | ||
184 | |||
185 | static int wuxga_nt_panel_get_modes(struct drm_panel *panel) | ||
186 | { | ||
187 | struct drm_display_mode *mode; | ||
188 | |||
189 | mode = drm_mode_duplicate(panel->drm, &default_mode); | ||
190 | if (!mode) { | ||
191 | dev_err(panel->drm->dev, "failed to add mode %ux%ux@%u\n", | ||
192 | default_mode.hdisplay, default_mode.vdisplay, | ||
193 | default_mode.vrefresh); | ||
194 | return -ENOMEM; | ||
195 | } | ||
196 | |||
197 | drm_mode_set_name(mode); | ||
198 | |||
199 | drm_mode_probed_add(panel->connector, mode); | ||
200 | |||
201 | panel->connector->display_info.width_mm = 217; | ||
202 | panel->connector->display_info.height_mm = 136; | ||
203 | |||
204 | return 1; | ||
205 | } | ||
206 | |||
207 | static const struct drm_panel_funcs wuxga_nt_panel_funcs = { | ||
208 | .disable = wuxga_nt_panel_disable, | ||
209 | .unprepare = wuxga_nt_panel_unprepare, | ||
210 | .prepare = wuxga_nt_panel_prepare, | ||
211 | .enable = wuxga_nt_panel_enable, | ||
212 | .get_modes = wuxga_nt_panel_get_modes, | ||
213 | }; | ||
214 | |||
215 | static const struct of_device_id wuxga_nt_of_match[] = { | ||
216 | { .compatible = "panasonic,vvx10f034n00", }, | ||
217 | { } | ||
218 | }; | ||
219 | MODULE_DEVICE_TABLE(of, wuxga_nt_of_match); | ||
220 | |||
221 | static int wuxga_nt_panel_add(struct wuxga_nt_panel *wuxga_nt) | ||
222 | { | ||
223 | struct device *dev = &wuxga_nt->dsi->dev; | ||
224 | struct device_node *np; | ||
225 | int ret; | ||
226 | |||
227 | wuxga_nt->mode = &default_mode; | ||
228 | |||
229 | wuxga_nt->supply = devm_regulator_get(dev, "power"); | ||
230 | if (IS_ERR(wuxga_nt->supply)) | ||
231 | return PTR_ERR(wuxga_nt->supply); | ||
232 | |||
233 | np = of_parse_phandle(dev->of_node, "backlight", 0); | ||
234 | if (np) { | ||
235 | wuxga_nt->backlight = of_find_backlight_by_node(np); | ||
236 | of_node_put(np); | ||
237 | |||
238 | if (!wuxga_nt->backlight) | ||
239 | return -EPROBE_DEFER; | ||
240 | } | ||
241 | |||
242 | drm_panel_init(&wuxga_nt->base); | ||
243 | wuxga_nt->base.funcs = &wuxga_nt_panel_funcs; | ||
244 | wuxga_nt->base.dev = &wuxga_nt->dsi->dev; | ||
245 | |||
246 | ret = drm_panel_add(&wuxga_nt->base); | ||
247 | if (ret < 0) | ||
248 | goto put_backlight; | ||
249 | |||
250 | return 0; | ||
251 | |||
252 | put_backlight: | ||
253 | if (wuxga_nt->backlight) | ||
254 | put_device(&wuxga_nt->backlight->dev); | ||
255 | |||
256 | return ret; | ||
257 | } | ||
258 | |||
259 | static void wuxga_nt_panel_del(struct wuxga_nt_panel *wuxga_nt) | ||
260 | { | ||
261 | if (wuxga_nt->base.dev) | ||
262 | drm_panel_remove(&wuxga_nt->base); | ||
263 | |||
264 | if (wuxga_nt->backlight) | ||
265 | put_device(&wuxga_nt->backlight->dev); | ||
266 | } | ||
267 | |||
268 | static int wuxga_nt_panel_probe(struct mipi_dsi_device *dsi) | ||
269 | { | ||
270 | struct wuxga_nt_panel *wuxga_nt; | ||
271 | int ret; | ||
272 | |||
273 | dsi->lanes = 4; | ||
274 | dsi->format = MIPI_DSI_FMT_RGB888; | ||
275 | dsi->mode_flags = MIPI_DSI_MODE_VIDEO | | ||
276 | MIPI_DSI_MODE_VIDEO_HSE | | ||
277 | MIPI_DSI_CLOCK_NON_CONTINUOUS | | ||
278 | MIPI_DSI_MODE_LPM; | ||
279 | |||
280 | wuxga_nt = devm_kzalloc(&dsi->dev, sizeof(*wuxga_nt), GFP_KERNEL); | ||
281 | if (!wuxga_nt) | ||
282 | return -ENOMEM; | ||
283 | |||
284 | mipi_dsi_set_drvdata(dsi, wuxga_nt); | ||
285 | |||
286 | wuxga_nt->dsi = dsi; | ||
287 | |||
288 | ret = wuxga_nt_panel_add(wuxga_nt); | ||
289 | if (ret < 0) | ||
290 | return ret; | ||
291 | |||
292 | return mipi_dsi_attach(dsi); | ||
293 | } | ||
294 | |||
295 | static int wuxga_nt_panel_remove(struct mipi_dsi_device *dsi) | ||
296 | { | ||
297 | struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi); | ||
298 | int ret; | ||
299 | |||
300 | ret = wuxga_nt_panel_disable(&wuxga_nt->base); | ||
301 | if (ret < 0) | ||
302 | dev_err(&dsi->dev, "failed to disable panel: %d\n", ret); | ||
303 | |||
304 | ret = mipi_dsi_detach(dsi); | ||
305 | if (ret < 0) | ||
306 | dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); | ||
307 | |||
308 | drm_panel_detach(&wuxga_nt->base); | ||
309 | wuxga_nt_panel_del(wuxga_nt); | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static void wuxga_nt_panel_shutdown(struct mipi_dsi_device *dsi) | ||
315 | { | ||
316 | struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi); | ||
317 | |||
318 | wuxga_nt_panel_disable(&wuxga_nt->base); | ||
319 | } | ||
320 | |||
321 | static struct mipi_dsi_driver wuxga_nt_panel_driver = { | ||
322 | .driver = { | ||
323 | .name = "panel-panasonic-vvx10f034n00", | ||
324 | .of_match_table = wuxga_nt_of_match, | ||
325 | }, | ||
326 | .probe = wuxga_nt_panel_probe, | ||
327 | .remove = wuxga_nt_panel_remove, | ||
328 | .shutdown = wuxga_nt_panel_shutdown, | ||
329 | }; | ||
330 | module_mipi_dsi_driver(wuxga_nt_panel_driver); | ||
331 | |||
332 | MODULE_AUTHOR("Werner Johansson <werner.johansson@sonymobile.com>"); | ||
333 | MODULE_DESCRIPTION("Panasonic VVX10F034N00 Novatek NT1397-based WUXGA (1920x1200) video mode panel driver"); | ||
334 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c new file mode 100644 index 000000000000..3aeb0bda4947 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c | |||
@@ -0,0 +1,387 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Red Hat | ||
3 | * Copyright (C) 2015 Sony Mobile Communications Inc. | ||
4 | * Author: Werner Johansson <werner.johansson@sonymobile.com> | ||
5 | * | ||
6 | * Based on AUO panel driver by Rob Clark <robdclark@gmail.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License version 2 as published by | ||
10 | * the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include <linux/backlight.h> | ||
22 | #include <linux/gpio/consumer.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/of.h> | ||
25 | #include <linux/regulator/consumer.h> | ||
26 | |||
27 | #include <drm/drmP.h> | ||
28 | #include <drm/drm_crtc.h> | ||
29 | #include <drm/drm_mipi_dsi.h> | ||
30 | #include <drm/drm_panel.h> | ||
31 | |||
32 | #include <video/mipi_display.h> | ||
33 | |||
34 | struct sharp_nt_panel { | ||
35 | struct drm_panel base; | ||
36 | struct mipi_dsi_device *dsi; | ||
37 | |||
38 | struct backlight_device *backlight; | ||
39 | struct regulator *supply; | ||
40 | struct gpio_desc *reset_gpio; | ||
41 | |||
42 | bool prepared; | ||
43 | bool enabled; | ||
44 | |||
45 | const struct drm_display_mode *mode; | ||
46 | }; | ||
47 | |||
48 | static inline struct sharp_nt_panel *to_sharp_nt_panel(struct drm_panel *panel) | ||
49 | { | ||
50 | return container_of(panel, struct sharp_nt_panel, base); | ||
51 | } | ||
52 | |||
53 | static int sharp_nt_panel_init(struct sharp_nt_panel *sharp_nt) | ||
54 | { | ||
55 | struct mipi_dsi_device *dsi = sharp_nt->dsi; | ||
56 | int ret; | ||
57 | |||
58 | dsi->mode_flags |= MIPI_DSI_MODE_LPM; | ||
59 | |||
60 | ret = mipi_dsi_dcs_exit_sleep_mode(dsi); | ||
61 | if (ret < 0) | ||
62 | return ret; | ||
63 | |||
64 | msleep(120); | ||
65 | |||
66 | /* Novatek two-lane operation */ | ||
67 | ret = mipi_dsi_dcs_write(dsi, 0xae, (u8[]){ 0x03 }, 1); | ||
68 | if (ret < 0) | ||
69 | return ret; | ||
70 | |||
71 | /* Set both MCU and RGB I/F to 24bpp */ | ||
72 | ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT | | ||
73 | (MIPI_DCS_PIXEL_FMT_24BIT << 4)); | ||
74 | if (ret < 0) | ||
75 | return ret; | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static int sharp_nt_panel_on(struct sharp_nt_panel *sharp_nt) | ||
81 | { | ||
82 | struct mipi_dsi_device *dsi = sharp_nt->dsi; | ||
83 | int ret; | ||
84 | |||
85 | dsi->mode_flags |= MIPI_DSI_MODE_LPM; | ||
86 | |||
87 | ret = mipi_dsi_dcs_set_display_on(dsi); | ||
88 | if (ret < 0) | ||
89 | return ret; | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static int sharp_nt_panel_off(struct sharp_nt_panel *sharp_nt) | ||
95 | { | ||
96 | struct mipi_dsi_device *dsi = sharp_nt->dsi; | ||
97 | int ret; | ||
98 | |||
99 | dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; | ||
100 | |||
101 | ret = mipi_dsi_dcs_set_display_off(dsi); | ||
102 | if (ret < 0) | ||
103 | return ret; | ||
104 | |||
105 | ret = mipi_dsi_dcs_enter_sleep_mode(dsi); | ||
106 | if (ret < 0) | ||
107 | return ret; | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | |||
113 | static int sharp_nt_panel_disable(struct drm_panel *panel) | ||
114 | { | ||
115 | struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel); | ||
116 | |||
117 | if (!sharp_nt->enabled) | ||
118 | return 0; | ||
119 | |||
120 | if (sharp_nt->backlight) { | ||
121 | sharp_nt->backlight->props.power = FB_BLANK_POWERDOWN; | ||
122 | backlight_update_status(sharp_nt->backlight); | ||
123 | } | ||
124 | |||
125 | sharp_nt->enabled = false; | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static int sharp_nt_panel_unprepare(struct drm_panel *panel) | ||
131 | { | ||
132 | struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel); | ||
133 | int ret; | ||
134 | |||
135 | if (!sharp_nt->prepared) | ||
136 | return 0; | ||
137 | |||
138 | ret = sharp_nt_panel_off(sharp_nt); | ||
139 | if (ret < 0) { | ||
140 | dev_err(panel->dev, "failed to set panel off: %d\n", ret); | ||
141 | return ret; | ||
142 | } | ||
143 | |||
144 | regulator_disable(sharp_nt->supply); | ||
145 | if (sharp_nt->reset_gpio) | ||
146 | gpiod_set_value(sharp_nt->reset_gpio, 0); | ||
147 | |||
148 | sharp_nt->prepared = false; | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int sharp_nt_panel_prepare(struct drm_panel *panel) | ||
154 | { | ||
155 | struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel); | ||
156 | int ret; | ||
157 | |||
158 | if (sharp_nt->prepared) | ||
159 | return 0; | ||
160 | |||
161 | ret = regulator_enable(sharp_nt->supply); | ||
162 | if (ret < 0) | ||
163 | return ret; | ||
164 | |||
165 | msleep(20); | ||
166 | |||
167 | if (sharp_nt->reset_gpio) { | ||
168 | gpiod_set_value(sharp_nt->reset_gpio, 1); | ||
169 | msleep(1); | ||
170 | gpiod_set_value(sharp_nt->reset_gpio, 0); | ||
171 | msleep(1); | ||
172 | gpiod_set_value(sharp_nt->reset_gpio, 1); | ||
173 | msleep(10); | ||
174 | } | ||
175 | |||
176 | ret = sharp_nt_panel_init(sharp_nt); | ||
177 | if (ret < 0) { | ||
178 | dev_err(panel->dev, "failed to init panel: %d\n", ret); | ||
179 | goto poweroff; | ||
180 | } | ||
181 | |||
182 | ret = sharp_nt_panel_on(sharp_nt); | ||
183 | if (ret < 0) { | ||
184 | dev_err(panel->dev, "failed to set panel on: %d\n", ret); | ||
185 | goto poweroff; | ||
186 | } | ||
187 | |||
188 | sharp_nt->prepared = true; | ||
189 | |||
190 | return 0; | ||
191 | |||
192 | poweroff: | ||
193 | regulator_disable(sharp_nt->supply); | ||
194 | if (sharp_nt->reset_gpio) | ||
195 | gpiod_set_value(sharp_nt->reset_gpio, 0); | ||
196 | return ret; | ||
197 | } | ||
198 | |||
199 | static int sharp_nt_panel_enable(struct drm_panel *panel) | ||
200 | { | ||
201 | struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel); | ||
202 | |||
203 | if (sharp_nt->enabled) | ||
204 | return 0; | ||
205 | |||
206 | if (sharp_nt->backlight) { | ||
207 | sharp_nt->backlight->props.power = FB_BLANK_UNBLANK; | ||
208 | backlight_update_status(sharp_nt->backlight); | ||
209 | } | ||
210 | |||
211 | sharp_nt->enabled = true; | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static const struct drm_display_mode default_mode = { | ||
217 | .clock = 41118, | ||
218 | .hdisplay = 540, | ||
219 | .hsync_start = 540 + 48, | ||
220 | .hsync_end = 540 + 48 + 80, | ||
221 | .htotal = 540 + 48 + 80 + 32, | ||
222 | .vdisplay = 960, | ||
223 | .vsync_start = 960 + 3, | ||
224 | .vsync_end = 960 + 3 + 15, | ||
225 | .vtotal = 960 + 3 + 15 + 1, | ||
226 | .vrefresh = 60, | ||
227 | }; | ||
228 | |||
229 | static int sharp_nt_panel_get_modes(struct drm_panel *panel) | ||
230 | { | ||
231 | struct drm_display_mode *mode; | ||
232 | |||
233 | mode = drm_mode_duplicate(panel->drm, &default_mode); | ||
234 | if (!mode) { | ||
235 | dev_err(panel->drm->dev, "failed to add mode %ux%ux@%u\n", | ||
236 | default_mode.hdisplay, default_mode.vdisplay, | ||
237 | default_mode.vrefresh); | ||
238 | return -ENOMEM; | ||
239 | } | ||
240 | |||
241 | drm_mode_set_name(mode); | ||
242 | |||
243 | drm_mode_probed_add(panel->connector, mode); | ||
244 | |||
245 | panel->connector->display_info.width_mm = 54; | ||
246 | panel->connector->display_info.height_mm = 95; | ||
247 | |||
248 | return 1; | ||
249 | } | ||
250 | |||
251 | static const struct drm_panel_funcs sharp_nt_panel_funcs = { | ||
252 | .disable = sharp_nt_panel_disable, | ||
253 | .unprepare = sharp_nt_panel_unprepare, | ||
254 | .prepare = sharp_nt_panel_prepare, | ||
255 | .enable = sharp_nt_panel_enable, | ||
256 | .get_modes = sharp_nt_panel_get_modes, | ||
257 | }; | ||
258 | |||
259 | static int sharp_nt_panel_add(struct sharp_nt_panel *sharp_nt) | ||
260 | { | ||
261 | struct device *dev = &sharp_nt->dsi->dev; | ||
262 | struct device_node *np; | ||
263 | int ret; | ||
264 | |||
265 | sharp_nt->mode = &default_mode; | ||
266 | |||
267 | sharp_nt->supply = devm_regulator_get(dev, "avdd"); | ||
268 | if (IS_ERR(sharp_nt->supply)) | ||
269 | return PTR_ERR(sharp_nt->supply); | ||
270 | |||
271 | sharp_nt->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); | ||
272 | if (IS_ERR(sharp_nt->reset_gpio)) { | ||
273 | dev_err(dev, "cannot get reset-gpios %ld\n", | ||
274 | PTR_ERR(sharp_nt->reset_gpio)); | ||
275 | sharp_nt->reset_gpio = NULL; | ||
276 | } else { | ||
277 | gpiod_set_value(sharp_nt->reset_gpio, 0); | ||
278 | } | ||
279 | |||
280 | np = of_parse_phandle(dev->of_node, "backlight", 0); | ||
281 | if (np) { | ||
282 | sharp_nt->backlight = of_find_backlight_by_node(np); | ||
283 | of_node_put(np); | ||
284 | |||
285 | if (!sharp_nt->backlight) | ||
286 | return -EPROBE_DEFER; | ||
287 | } | ||
288 | |||
289 | drm_panel_init(&sharp_nt->base); | ||
290 | sharp_nt->base.funcs = &sharp_nt_panel_funcs; | ||
291 | sharp_nt->base.dev = &sharp_nt->dsi->dev; | ||
292 | |||
293 | ret = drm_panel_add(&sharp_nt->base); | ||
294 | if (ret < 0) | ||
295 | goto put_backlight; | ||
296 | |||
297 | return 0; | ||
298 | |||
299 | put_backlight: | ||
300 | if (sharp_nt->backlight) | ||
301 | put_device(&sharp_nt->backlight->dev); | ||
302 | |||
303 | return ret; | ||
304 | } | ||
305 | |||
306 | static void sharp_nt_panel_del(struct sharp_nt_panel *sharp_nt) | ||
307 | { | ||
308 | if (sharp_nt->base.dev) | ||
309 | drm_panel_remove(&sharp_nt->base); | ||
310 | |||
311 | if (sharp_nt->backlight) | ||
312 | put_device(&sharp_nt->backlight->dev); | ||
313 | } | ||
314 | |||
315 | static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi) | ||
316 | { | ||
317 | struct sharp_nt_panel *sharp_nt; | ||
318 | int ret; | ||
319 | |||
320 | dsi->lanes = 2; | ||
321 | dsi->format = MIPI_DSI_FMT_RGB888; | ||
322 | dsi->mode_flags = MIPI_DSI_MODE_VIDEO | | ||
323 | MIPI_DSI_MODE_VIDEO_HSE | | ||
324 | MIPI_DSI_CLOCK_NON_CONTINUOUS | | ||
325 | MIPI_DSI_MODE_EOT_PACKET; | ||
326 | |||
327 | sharp_nt = devm_kzalloc(&dsi->dev, sizeof(*sharp_nt), GFP_KERNEL); | ||
328 | if (!sharp_nt) | ||
329 | return -ENOMEM; | ||
330 | |||
331 | mipi_dsi_set_drvdata(dsi, sharp_nt); | ||
332 | |||
333 | sharp_nt->dsi = dsi; | ||
334 | |||
335 | ret = sharp_nt_panel_add(sharp_nt); | ||
336 | if (ret < 0) | ||
337 | return ret; | ||
338 | |||
339 | return mipi_dsi_attach(dsi); | ||
340 | } | ||
341 | |||
342 | static int sharp_nt_panel_remove(struct mipi_dsi_device *dsi) | ||
343 | { | ||
344 | struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi); | ||
345 | int ret; | ||
346 | |||
347 | ret = sharp_nt_panel_disable(&sharp_nt->base); | ||
348 | if (ret < 0) | ||
349 | dev_err(&dsi->dev, "failed to disable panel: %d\n", ret); | ||
350 | |||
351 | ret = mipi_dsi_detach(dsi); | ||
352 | if (ret < 0) | ||
353 | dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); | ||
354 | |||
355 | drm_panel_detach(&sharp_nt->base); | ||
356 | sharp_nt_panel_del(sharp_nt); | ||
357 | |||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | static void sharp_nt_panel_shutdown(struct mipi_dsi_device *dsi) | ||
362 | { | ||
363 | struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi); | ||
364 | |||
365 | sharp_nt_panel_disable(&sharp_nt->base); | ||
366 | } | ||
367 | |||
368 | static const struct of_device_id sharp_nt_of_match[] = { | ||
369 | { .compatible = "sharp,ls043t1le01-qhd", }, | ||
370 | { } | ||
371 | }; | ||
372 | MODULE_DEVICE_TABLE(of, sharp_nt_of_match); | ||
373 | |||
374 | static struct mipi_dsi_driver sharp_nt_panel_driver = { | ||
375 | .driver = { | ||
376 | .name = "panel-sharp-ls043t1le01-qhd", | ||
377 | .of_match_table = sharp_nt_of_match, | ||
378 | }, | ||
379 | .probe = sharp_nt_panel_probe, | ||
380 | .remove = sharp_nt_panel_remove, | ||
381 | .shutdown = sharp_nt_panel_shutdown, | ||
382 | }; | ||
383 | module_mipi_dsi_driver(sharp_nt_panel_driver); | ||
384 | |||
385 | MODULE_AUTHOR("Werner Johansson <werner.johansson@sonymobile.com>"); | ||
386 | MODULE_DESCRIPTION("Sharp LS043T1LE01 NT35565-based qHD (540x960) video mode panel driver"); | ||
387 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index f97b73ec4713..f88a631c43ab 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c | |||
@@ -44,6 +44,10 @@ struct panel_desc { | |||
44 | 44 | ||
45 | unsigned int bpc; | 45 | unsigned int bpc; |
46 | 46 | ||
47 | /** | ||
48 | * @width: width (in millimeters) of the panel's active display area | ||
49 | * @height: height (in millimeters) of the panel's active display area | ||
50 | */ | ||
47 | struct { | 51 | struct { |
48 | unsigned int width; | 52 | unsigned int width; |
49 | unsigned int height; | 53 | unsigned int height; |
@@ -832,6 +836,34 @@ static const struct panel_desc innolux_g121i1_l01 = { | |||
832 | }, | 836 | }, |
833 | }; | 837 | }; |
834 | 838 | ||
839 | static const struct drm_display_mode innolux_g121x1_l03_mode = { | ||
840 | .clock = 65000, | ||
841 | .hdisplay = 1024, | ||
842 | .hsync_start = 1024 + 0, | ||
843 | .hsync_end = 1024 + 1, | ||
844 | .htotal = 1024 + 0 + 1 + 320, | ||
845 | .vdisplay = 768, | ||
846 | .vsync_start = 768 + 38, | ||
847 | .vsync_end = 768 + 38 + 1, | ||
848 | .vtotal = 768 + 38 + 1 + 0, | ||
849 | .vrefresh = 60, | ||
850 | }; | ||
851 | |||
852 | static const struct panel_desc innolux_g121x1_l03 = { | ||
853 | .modes = &innolux_g121x1_l03_mode, | ||
854 | .num_modes = 1, | ||
855 | .bpc = 6, | ||
856 | .size = { | ||
857 | .width = 246, | ||
858 | .height = 185, | ||
859 | }, | ||
860 | .delay = { | ||
861 | .enable = 200, | ||
862 | .unprepare = 200, | ||
863 | .disable = 400, | ||
864 | }, | ||
865 | }; | ||
866 | |||
835 | static const struct drm_display_mode innolux_n116bge_mode = { | 867 | static const struct drm_display_mode innolux_n116bge_mode = { |
836 | .clock = 76420, | 868 | .clock = 76420, |
837 | .hdisplay = 1366, | 869 | .hdisplay = 1366, |
@@ -902,6 +934,30 @@ static const struct panel_desc innolux_zj070na_01p = { | |||
902 | }, | 934 | }, |
903 | }; | 935 | }; |
904 | 936 | ||
937 | static const struct display_timing kyo_tcg121xglp_timing = { | ||
938 | .pixelclock = { 52000000, 65000000, 71000000 }, | ||
939 | .hactive = { 1024, 1024, 1024 }, | ||
940 | .hfront_porch = { 2, 2, 2 }, | ||
941 | .hback_porch = { 2, 2, 2 }, | ||
942 | .hsync_len = { 86, 124, 244 }, | ||
943 | .vactive = { 768, 768, 768 }, | ||
944 | .vfront_porch = { 2, 2, 2 }, | ||
945 | .vback_porch = { 2, 2, 2 }, | ||
946 | .vsync_len = { 6, 34, 73 }, | ||
947 | .flags = DISPLAY_FLAGS_DE_HIGH, | ||
948 | }; | ||
949 | |||
950 | static const struct panel_desc kyo_tcg121xglp = { | ||
951 | .timings = &kyo_tcg121xglp_timing, | ||
952 | .num_timings = 1, | ||
953 | .bpc = 8, | ||
954 | .size = { | ||
955 | .width = 246, | ||
956 | .height = 184, | ||
957 | }, | ||
958 | .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, | ||
959 | }; | ||
960 | |||
905 | static const struct drm_display_mode lg_lb070wv8_mode = { | 961 | static const struct drm_display_mode lg_lb070wv8_mode = { |
906 | .clock = 33246, | 962 | .clock = 33246, |
907 | .hdisplay = 800, | 963 | .hdisplay = 800, |
@@ -1027,6 +1083,30 @@ static const struct panel_desc ortustech_com43h4m85ulc = { | |||
1027 | .bus_format = MEDIA_BUS_FMT_RGB888_1X24, | 1083 | .bus_format = MEDIA_BUS_FMT_RGB888_1X24, |
1028 | }; | 1084 | }; |
1029 | 1085 | ||
1086 | static const struct drm_display_mode qd43003c0_40_mode = { | ||
1087 | .clock = 9000, | ||
1088 | .hdisplay = 480, | ||
1089 | .hsync_start = 480 + 8, | ||
1090 | .hsync_end = 480 + 8 + 4, | ||
1091 | .htotal = 480 + 8 + 4 + 39, | ||
1092 | .vdisplay = 272, | ||
1093 | .vsync_start = 272 + 4, | ||
1094 | .vsync_end = 272 + 4 + 10, | ||
1095 | .vtotal = 272 + 4 + 10 + 2, | ||
1096 | .vrefresh = 60, | ||
1097 | }; | ||
1098 | |||
1099 | static const struct panel_desc qd43003c0_40 = { | ||
1100 | .modes = &qd43003c0_40_mode, | ||
1101 | .num_modes = 1, | ||
1102 | .bpc = 8, | ||
1103 | .size = { | ||
1104 | .width = 95, | ||
1105 | .height = 53, | ||
1106 | }, | ||
1107 | .bus_format = MEDIA_BUS_FMT_RGB888_1X24, | ||
1108 | }; | ||
1109 | |||
1030 | static const struct drm_display_mode samsung_ltn101nt05_mode = { | 1110 | static const struct drm_display_mode samsung_ltn101nt05_mode = { |
1031 | .clock = 54030, | 1111 | .clock = 54030, |
1032 | .hdisplay = 1024, | 1112 | .hdisplay = 1024, |
@@ -1158,6 +1238,9 @@ static const struct of_device_id platform_of_match[] = { | |||
1158 | .compatible ="innolux,g121i1-l01", | 1238 | .compatible ="innolux,g121i1-l01", |
1159 | .data = &innolux_g121i1_l01 | 1239 | .data = &innolux_g121i1_l01 |
1160 | }, { | 1240 | }, { |
1241 | .compatible = "innolux,g121x1-l03", | ||
1242 | .data = &innolux_g121x1_l03, | ||
1243 | }, { | ||
1161 | .compatible = "innolux,n116bge", | 1244 | .compatible = "innolux,n116bge", |
1162 | .data = &innolux_n116bge, | 1245 | .data = &innolux_n116bge, |
1163 | }, { | 1246 | }, { |
@@ -1167,6 +1250,9 @@ static const struct of_device_id platform_of_match[] = { | |||
1167 | .compatible = "innolux,zj070na-01p", | 1250 | .compatible = "innolux,zj070na-01p", |
1168 | .data = &innolux_zj070na_01p, | 1251 | .data = &innolux_zj070na_01p, |
1169 | }, { | 1252 | }, { |
1253 | .compatible = "kyo,tcg121xglp", | ||
1254 | .data = &kyo_tcg121xglp, | ||
1255 | }, { | ||
1170 | .compatible = "lg,lb070wv8", | 1256 | .compatible = "lg,lb070wv8", |
1171 | .data = &lg_lb070wv8, | 1257 | .data = &lg_lb070wv8, |
1172 | }, { | 1258 | }, { |
@@ -1182,6 +1268,9 @@ static const struct of_device_id platform_of_match[] = { | |||
1182 | .compatible = "ortustech,com43h4m85ulc", | 1268 | .compatible = "ortustech,com43h4m85ulc", |
1183 | .data = &ortustech_com43h4m85ulc, | 1269 | .data = &ortustech_com43h4m85ulc, |
1184 | }, { | 1270 | }, { |
1271 | .compatible = "qiaodian,qd43003c0-40", | ||
1272 | .data = &qd43003c0_40, | ||
1273 | }, { | ||
1185 | .compatible = "samsung,ltn101nt05", | 1274 | .compatible = "samsung,ltn101nt05", |
1186 | .data = &samsung_ltn101nt05, | 1275 | .data = &samsung_ltn101nt05, |
1187 | }, { | 1276 | }, { |
@@ -1263,6 +1352,36 @@ static const struct panel_desc_dsi auo_b080uan01 = { | |||
1263 | .lanes = 4, | 1352 | .lanes = 4, |
1264 | }; | 1353 | }; |
1265 | 1354 | ||
1355 | static const struct drm_display_mode boe_tv080wum_nl0_mode = { | ||
1356 | .clock = 160000, | ||
1357 | .hdisplay = 1200, | ||
1358 | .hsync_start = 1200 + 120, | ||
1359 | .hsync_end = 1200 + 120 + 20, | ||
1360 | .htotal = 1200 + 120 + 20 + 21, | ||
1361 | .vdisplay = 1920, | ||
1362 | .vsync_start = 1920 + 21, | ||
1363 | .vsync_end = 1920 + 21 + 3, | ||
1364 | .vtotal = 1920 + 21 + 3 + 18, | ||
1365 | .vrefresh = 60, | ||
1366 | .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, | ||
1367 | }; | ||
1368 | |||
1369 | static const struct panel_desc_dsi boe_tv080wum_nl0 = { | ||
1370 | .desc = { | ||
1371 | .modes = &boe_tv080wum_nl0_mode, | ||
1372 | .num_modes = 1, | ||
1373 | .size = { | ||
1374 | .width = 107, | ||
1375 | .height = 172, | ||
1376 | }, | ||
1377 | }, | ||
1378 | .flags = MIPI_DSI_MODE_VIDEO | | ||
1379 | MIPI_DSI_MODE_VIDEO_BURST | | ||
1380 | MIPI_DSI_MODE_VIDEO_SYNC_PULSE, | ||
1381 | .format = MIPI_DSI_FMT_RGB888, | ||
1382 | .lanes = 4, | ||
1383 | }; | ||
1384 | |||
1266 | static const struct drm_display_mode lg_ld070wx3_sl01_mode = { | 1385 | static const struct drm_display_mode lg_ld070wx3_sl01_mode = { |
1267 | .clock = 71000, | 1386 | .clock = 71000, |
1268 | .hdisplay = 800, | 1387 | .hdisplay = 800, |
@@ -1348,11 +1467,15 @@ static const struct panel_desc_dsi panasonic_vvx10f004b00 = { | |||
1348 | .lanes = 4, | 1467 | .lanes = 4, |
1349 | }; | 1468 | }; |
1350 | 1469 | ||
1470 | |||
1351 | static const struct of_device_id dsi_of_match[] = { | 1471 | static const struct of_device_id dsi_of_match[] = { |
1352 | { | 1472 | { |
1353 | .compatible = "auo,b080uan01", | 1473 | .compatible = "auo,b080uan01", |
1354 | .data = &auo_b080uan01 | 1474 | .data = &auo_b080uan01 |
1355 | }, { | 1475 | }, { |
1476 | .compatible = "boe,tv080wum-nl0", | ||
1477 | .data = &boe_tv080wum_nl0 | ||
1478 | }, { | ||
1356 | .compatible = "lg,ld070wx3-sl01", | 1479 | .compatible = "lg,ld070wx3-sl01", |
1357 | .data = &lg_ld070wx3_sl01 | 1480 | .data = &lg_ld070wx3_sl01 |
1358 | }, { | 1481 | }, { |
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index f1d8d0dbb4f1..1b3b1f8c8cdf 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h | |||
@@ -163,9 +163,36 @@ static inline struct mipi_dsi_device *to_mipi_dsi_device(struct device *dev) | |||
163 | return container_of(dev, struct mipi_dsi_device, dev); | 163 | return container_of(dev, struct mipi_dsi_device, dev); |
164 | } | 164 | } |
165 | 165 | ||
166 | /** | ||
167 | * mipi_dsi_pixel_format_to_bpp - obtain the number of bits per pixel for any | ||
168 | * given pixel format defined by the MIPI DSI | ||
169 | * specification | ||
170 | * @fmt: MIPI DSI pixel format | ||
171 | * | ||
172 | * Returns: The number of bits per pixel of the given pixel format. | ||
173 | */ | ||
174 | static inline int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt) | ||
175 | { | ||
176 | switch (fmt) { | ||
177 | case MIPI_DSI_FMT_RGB888: | ||
178 | case MIPI_DSI_FMT_RGB666: | ||
179 | return 24; | ||
180 | |||
181 | case MIPI_DSI_FMT_RGB666_PACKED: | ||
182 | return 18; | ||
183 | |||
184 | case MIPI_DSI_FMT_RGB565: | ||
185 | return 16; | ||
186 | } | ||
187 | |||
188 | return -EINVAL; | ||
189 | } | ||
190 | |||
166 | struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np); | 191 | struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np); |
167 | int mipi_dsi_attach(struct mipi_dsi_device *dsi); | 192 | int mipi_dsi_attach(struct mipi_dsi_device *dsi); |
168 | int mipi_dsi_detach(struct mipi_dsi_device *dsi); | 193 | int mipi_dsi_detach(struct mipi_dsi_device *dsi); |
194 | int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi); | ||
195 | int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi); | ||
169 | int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi, | 196 | int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi, |
170 | u16 value); | 197 | u16 value); |
171 | 198 | ||