diff options
author | Dave Airlie <airlied@redhat.com> | 2018-02-22 20:12:52 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2018-02-22 20:12:52 -0500 |
commit | 727edc744098e2a3d2f9f9ce53edb49cb7817ea1 (patch) | |
tree | 0e489963c3f68c6e7615296056ff2402de41e2de | |
parent | e53a2079f46aadb4c3d86ba2528e2b5b7eae49dc (diff) | |
parent | 2b91e3c43b4f3d3cd4d84a31cfbe6b165d89b70e (diff) |
Merge tag 'drm-misc-next-2018-02-21' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for 4.17:
Cross-subsystem Changes:
- Backlight helpers to enable/disable and find devices in dt (Meghana)
Core Changes:
- Documentation improvements (Chris/Daniel/Jani)
- simple_kms_helper: Add mode_valid() support (Linus)
- mm: Fix bug in interval_tree causing nodes to be out-of-order (Chris)
Driver Changes:
- tinydrm/panel: Use the new backlight helpers (Meghana)
- rockchip: Support gem_prime_import_sg_table + some fixes (Various)
- sun4i: Add A83T HDMI support using dw-hdmi (Jernej)
Cc: Meghana Madhyastha <meghana.madhyastha@gmail.com>
Cc: Jani Nikula <jani.nikula@intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Heiko Stuebner <heiko@sntech.de>
Cc: Jernej Skrabec <jernej.skrabec@siol.net>
* tag 'drm-misc-next-2018-02-21' of git://anongit.freedesktop.org/drm/drm-misc: (41 commits)
drm/omapdrm: Use of_find_backlight helper
drm/panel: Use of_find_backlight helper
drm/omapdrm: Use backlight_enable/disable helpers
drm/panel: Use backlight_enable/disable helpers
drm/tinydrm: Call devres version of of_find_backlight
drm/tinydrm: Replace tinydrm_of_find_backlight with of_find_backlight
drm/tinydrm: Convert tinydrm_enable/disable_backlight to backlight_enable/disable
drm: add documentation for tv connector state margins
drm/doc: Use new substruct support
drm/doc: Polish for drm_mode_parse_command_line_for_connector
drm/docs: Document "scaling mode" property better
drm/docs: Align layout of optional plane blending properties
drm/docs: Discourage adding more to kms-properties.csv
drm: simple_kms_helper: Add mode_valid() callback support
drm/todo: Add idr_init_base todo
drm: Use idr_init_base(1) when using id==0 for invalid
drm: NULL pointer dereference [null-pointer-deref] (CWE 476) problem
drm: NULL pointer dereference [null-pointer-deref] (CWE 476) problem
dma-buf/sw_sync: Fix kerneldoc warnings
drm: Fix kerneldoc warnings for drm_lease
...
53 files changed, 1253 insertions, 358 deletions
diff --git a/Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt new file mode 100644 index 000000000000..8df7d2e393d6 --- /dev/null +++ b/Documentation/devicetree/bindings/display/rockchip/cdn-dp-rockchip.txt | |||
@@ -0,0 +1,74 @@ | |||
1 | Rockchip RK3399 specific extensions to the cdn Display Port | ||
2 | ================================ | ||
3 | |||
4 | Required properties: | ||
5 | - compatible: must be "rockchip,rk3399-cdn-dp" | ||
6 | |||
7 | - reg: physical base address of the controller and length | ||
8 | |||
9 | - clocks: from common clock binding: handle to dp clock. | ||
10 | |||
11 | - clock-names: from common clock binding: | ||
12 | Required elements: "core-clk" "pclk" "spdif" "grf" | ||
13 | |||
14 | - resets : a list of phandle + reset specifier pairs | ||
15 | - reset-names : string of reset names | ||
16 | Required elements: "apb", "core", "dptx", "spdif" | ||
17 | - power-domains : power-domain property defined with a phandle | ||
18 | to respective power domain. | ||
19 | - assigned-clocks: main clock, should be <&cru SCLK_DP_CORE> | ||
20 | - assigned-clock-rates : the DP core clk frequency, shall be: 100000000 | ||
21 | |||
22 | - rockchip,grf: this soc should set GRF regs, so need get grf here. | ||
23 | |||
24 | - ports: contain a port nodes with endpoint definitions as defined in | ||
25 | Documentation/devicetree/bindings/media/video-interfaces.txt. | ||
26 | contained 2 endpoints, connecting to the output of vop. | ||
27 | |||
28 | - phys: from general PHY binding: the phandle for the PHY device. | ||
29 | |||
30 | - extcon: extcon specifier for the Power Delivery | ||
31 | |||
32 | - #sound-dai-cells = it must be 1 if your system is using 2 DAIs: I2S, SPDIF | ||
33 | |||
34 | ------------------------------------------------------------------------------- | ||
35 | |||
36 | Example: | ||
37 | cdn_dp: dp@fec00000 { | ||
38 | compatible = "rockchip,rk3399-cdn-dp"; | ||
39 | reg = <0x0 0xfec00000 0x0 0x100000>; | ||
40 | interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>; | ||
41 | clocks = <&cru SCLK_DP_CORE>, <&cru PCLK_DP_CTRL>, | ||
42 | <&cru SCLK_SPDIF_REC_DPTX>, <&cru PCLK_VIO_GRF>; | ||
43 | clock-names = "core-clk", "pclk", "spdif", "grf"; | ||
44 | assigned-clocks = <&cru SCLK_DP_CORE>; | ||
45 | assigned-clock-rates = <100000000>; | ||
46 | power-domains = <&power RK3399_PD_HDCP>; | ||
47 | phys = <&tcphy0_dp>, <&tcphy1_dp>; | ||
48 | resets = <&cru SRST_DPTX_SPDIF_REC>; | ||
49 | reset-names = "spdif"; | ||
50 | extcon = <&fusb0>, <&fusb1>; | ||
51 | rockchip,grf = <&grf>; | ||
52 | #address-cells = <1>; | ||
53 | #size-cells = <0>; | ||
54 | #sound-dai-cells = <1>; | ||
55 | |||
56 | ports { | ||
57 | #address-cells = <1>; | ||
58 | #size-cells = <0>; | ||
59 | |||
60 | dp_in: port { | ||
61 | #address-cells = <1>; | ||
62 | #size-cells = <0>; | ||
63 | dp_in_vopb: endpoint@0 { | ||
64 | reg = <0>; | ||
65 | remote-endpoint = <&vopb_out_dp>; | ||
66 | }; | ||
67 | |||
68 | dp_in_vopl: endpoint@1 { | ||
69 | reg = <1>; | ||
70 | remote-endpoint = <&vopl_out_dp>; | ||
71 | }; | ||
72 | }; | ||
73 | }; | ||
74 | }; | ||
diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt index cd626ee1147a..b995bfee734a 100644 --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | |||
@@ -64,6 +64,52 @@ Required properties: | |||
64 | first port should be the input endpoint. The second should be the | 64 | first port should be the input endpoint. The second should be the |
65 | output, usually to an HDMI connector. | 65 | output, usually to an HDMI connector. |
66 | 66 | ||
67 | DWC HDMI TX Encoder | ||
68 | ------------------- | ||
69 | |||
70 | The HDMI transmitter is a Synopsys DesignWare HDMI 1.4 TX controller IP | ||
71 | with Allwinner's own PHY IP. It supports audio and video outputs and CEC. | ||
72 | |||
73 | These DT bindings follow the Synopsys DWC HDMI TX bindings defined in | ||
74 | Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt with the | ||
75 | following device-specific properties. | ||
76 | |||
77 | Required properties: | ||
78 | |||
79 | - compatible: value must be one of: | ||
80 | * "allwinner,sun8i-a83t-dw-hdmi" | ||
81 | - reg: base address and size of memory-mapped region | ||
82 | - reg-io-width: See dw_hdmi.txt. Shall be 1. | ||
83 | - interrupts: HDMI interrupt number | ||
84 | - clocks: phandles to the clocks feeding the HDMI encoder | ||
85 | * iahb: the HDMI bus clock | ||
86 | * isfr: the HDMI register clock | ||
87 | * tmds: TMDS clock | ||
88 | - clock-names: the clock names mentioned above | ||
89 | - resets: phandle to the reset controller | ||
90 | - reset-names: must be "ctrl" | ||
91 | - phys: phandle to the DWC HDMI PHY | ||
92 | - phy-names: must be "phy" | ||
93 | |||
94 | - ports: A ports node with endpoint definitions as defined in | ||
95 | Documentation/devicetree/bindings/media/video-interfaces.txt. The | ||
96 | first port should be the input endpoint. The second should be the | ||
97 | output, usually to an HDMI connector. | ||
98 | |||
99 | DWC HDMI PHY | ||
100 | ------------ | ||
101 | |||
102 | Required properties: | ||
103 | - compatible: value must be one of: | ||
104 | * allwinner,sun8i-a83t-hdmi-phy | ||
105 | - reg: base address and size of memory-mapped region | ||
106 | - clocks: phandles to the clocks feeding the HDMI PHY | ||
107 | * bus: the HDMI PHY interface clock | ||
108 | * mod: the HDMI PHY module clock | ||
109 | - clock-names: the clock names mentioned above | ||
110 | - resets: phandle to the reset controller driving the PHY | ||
111 | - reset-names: must be "phy" | ||
112 | |||
67 | TV Encoder | 113 | TV Encoder |
68 | ---------- | 114 | ---------- |
69 | 115 | ||
@@ -94,24 +140,26 @@ Required properties: | |||
94 | * allwinner,sun7i-a20-tcon | 140 | * allwinner,sun7i-a20-tcon |
95 | * allwinner,sun8i-a33-tcon | 141 | * allwinner,sun8i-a33-tcon |
96 | * allwinner,sun8i-a83t-tcon-lcd | 142 | * allwinner,sun8i-a83t-tcon-lcd |
143 | * allwinner,sun8i-a83t-tcon-tv | ||
97 | * allwinner,sun8i-v3s-tcon | 144 | * allwinner,sun8i-v3s-tcon |
98 | - reg: base address and size of memory-mapped region | 145 | - reg: base address and size of memory-mapped region |
99 | - interrupts: interrupt associated to this IP | 146 | - interrupts: interrupt associated to this IP |
100 | - clocks: phandles to the clocks feeding the TCON. Three are needed: | 147 | - clocks: phandles to the clocks feeding the TCON. |
101 | - 'ahb': the interface clocks | 148 | - 'ahb': the interface clocks |
102 | - 'tcon-ch0': The clock driving the TCON channel 0 | 149 | - 'tcon-ch0': The clock driving the TCON channel 0, except for A83T TV TCON |
103 | - resets: phandles to the reset controllers driving the encoder | 150 | - resets: phandles to the reset controllers driving the encoder |
104 | - "lcd": the reset line for the TCON channel 0 | 151 | - "lcd": the reset line for the TCON channel 0 |
105 | 152 | ||
106 | - clock-names: the clock names mentioned above | 153 | - clock-names: the clock names mentioned above |
107 | - reset-names: the reset names mentioned above | 154 | - reset-names: the reset names mentioned above |
108 | - clock-output-names: Name of the pixel clock created | 155 | - clock-output-names: Name of the pixel clock created, if TCON supports |
156 | channel 0. | ||
109 | 157 | ||
110 | - ports: A ports node with endpoint definitions as defined in | 158 | - ports: A ports node with endpoint definitions as defined in |
111 | Documentation/devicetree/bindings/media/video-interfaces.txt. The | 159 | Documentation/devicetree/bindings/media/video-interfaces.txt. The |
112 | first port should be the input endpoint, the second one the output | 160 | first port should be the input endpoint, the second one the output |
113 | 161 | ||
114 | The output may have multiple endpoints. The TCON has two channels, | 162 | The output may have multiple endpoints. TCON can have 1 or 2 channels, |
115 | usually with the first channel being used for the panels interfaces | 163 | usually with the first channel being used for the panels interfaces |
116 | (RGB, LVDS, etc.), and the second being used for the outputs that | 164 | (RGB, LVDS, etc.), and the second being used for the outputs that |
117 | require another controller (TV Encoder, HDMI, etc.). The endpoints | 165 | require another controller (TV Encoder, HDMI, etc.). The endpoints |
@@ -122,8 +170,8 @@ Required properties: | |||
122 | On SoCs other than the A33 and V3s, there is one more clock required: | 170 | On SoCs other than the A33 and V3s, there is one more clock required: |
123 | - 'tcon-ch1': The clock driving the TCON channel 1 | 171 | - 'tcon-ch1': The clock driving the TCON channel 1 |
124 | 172 | ||
125 | On SoCs that support LVDS (all SoCs but the A13, H3, H5 and V3s), you | 173 | When TCON support LVDS (all TCONs except TV TCON on A83T and those found |
126 | need one more reset line: | 174 | in A13, H3, H5 and V3s SoCs), you need one more reset line: |
127 | - 'lvds': The reset line driving the LVDS logic | 175 | - 'lvds': The reset line driving the LVDS logic |
128 | 176 | ||
129 | And on the A23, A31, A31s and A33, you need one more clock line: | 177 | And on the A23, A31, A31s and A33, you need one more clock line: |
@@ -226,6 +274,7 @@ supported. | |||
226 | Required properties: | 274 | Required properties: |
227 | - compatible: value must be one of: | 275 | - compatible: value must be one of: |
228 | * allwinner,sun8i-a83t-de2-mixer-0 | 276 | * allwinner,sun8i-a83t-de2-mixer-0 |
277 | * allwinner,sun8i-a83t-de2-mixer-1 | ||
229 | * allwinner,sun8i-v3s-de2-mixer | 278 | * allwinner,sun8i-v3s-de2-mixer |
230 | - reg: base address and size of the memory-mapped region. | 279 | - reg: base address and size of the memory-mapped region. |
231 | - clocks: phandles to the clocks feeding the mixer | 280 | - clocks: phandles to the clocks feeding the mixer |
diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index 2dcf5b42015d..56a3780e39b8 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst | |||
@@ -547,8 +547,9 @@ Explicit Fencing Properties | |||
547 | Existing KMS Properties | 547 | Existing KMS Properties |
548 | ----------------------- | 548 | ----------------------- |
549 | 549 | ||
550 | The following table gives description of drm properties exposed by | 550 | The following table gives description of drm properties exposed by various |
551 | various modules/drivers. | 551 | modules/drivers. Because this table is very unwieldy, do not add any new |
552 | properties here. Instead document them in a section above. | ||
552 | 553 | ||
553 | .. csv-table:: | 554 | .. csv-table:: |
554 | :header-rows: 1 | 555 | :header-rows: 1 |
diff --git a/Documentation/gpu/kms-properties.csv b/Documentation/gpu/kms-properties.csv index 927b65e14219..6b28b014cb7d 100644 --- a/Documentation/gpu/kms-properties.csv +++ b/Documentation/gpu/kms-properties.csv | |||
@@ -1,5 +1,4 @@ | |||
1 | Owner Module/Drivers,Group,Property Name,Type,Property Values,Object attached,Description/Restrictions | 1 | Owner Module/Drivers,Group,Property Name,Type,Property Values,Object attached,Description/Restrictions |
2 | ,,“scaling mode”,ENUM,"{ ""None"", ""Full"", ""Center"", ""Full aspect"" }",Connector,"Supported by: amdgpu, gma500, i915, nouveau and radeon." | ||
3 | ,DVI-I,“subconnector”,ENUM,"{ “Unknown”, “DVI-D”, “DVI-A” }",Connector,TBD | 2 | ,DVI-I,“subconnector”,ENUM,"{ “Unknown”, “DVI-D”, “DVI-A” }",Connector,TBD |
4 | ,,“select subconnector”,ENUM,"{ “Automatic”, “DVI-D”, “DVI-A” }",Connector,TBD | 3 | ,,“select subconnector”,ENUM,"{ “Automatic”, “DVI-D”, “DVI-A” }",Connector,TBD |
5 | ,TV,“subconnector”,ENUM,"{ ""Unknown"", ""Composite"", ""SVIDEO"", ""Component"", ""SCART"" }",Connector,TBD | 4 | ,TV,“subconnector”,ENUM,"{ ""Unknown"", ""Composite"", ""SVIDEO"", ""Component"", ""SCART"" }",Connector,TBD |
diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 1e593370f64f..1a0a413eeced 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst | |||
@@ -212,6 +212,16 @@ probably use drm_fb_helper_fbdev_teardown(). | |||
212 | 212 | ||
213 | Contact: Maintainer of the driver you plan to convert | 213 | Contact: Maintainer of the driver you plan to convert |
214 | 214 | ||
215 | idr_init_base() | ||
216 | --------------- | ||
217 | |||
218 | DRM core&drivers uses a lot of idr (integer lookup directories) for mapping | ||
219 | userspace IDs to internal objects, and in most places ID=0 means NULL and hence | ||
220 | is never used. Switching to idr_init_base() for these would make the idr more | ||
221 | efficient. | ||
222 | |||
223 | Contact: Daniel Vetter | ||
224 | |||
215 | Core refactorings | 225 | Core refactorings |
216 | ================= | 226 | ================= |
217 | 227 | ||
diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index 7779bdbd18d1..3d78ca89a605 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c | |||
@@ -235,10 +235,10 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) | |||
235 | 235 | ||
236 | /** | 236 | /** |
237 | * sync_pt_create() - creates a sync pt | 237 | * sync_pt_create() - creates a sync pt |
238 | * @parent: fence's parent sync_timeline | 238 | * @obj: parent sync_timeline |
239 | * @inc: value of the fence | 239 | * @value: value of the fence |
240 | * | 240 | * |
241 | * Creates a new sync_pt as a child of @parent. @size bytes will be | 241 | * Creates a new sync_pt (fence) as a child of @parent. @size bytes will be |
242 | * allocated allowing for implementation specific data to be kept after | 242 | * allocated allowing for implementation specific data to be kept after |
243 | * the generic sync_timeline struct. Returns the sync_pt object or | 243 | * the generic sync_timeline struct. Returns the sync_pt object or |
244 | * NULL in case of error. | 244 | * NULL in case of error. |
diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c index 704e879711e4..b1d5aee46316 100644 --- a/drivers/gpu/drm/bochs/bochs_mm.c +++ b/drivers/gpu/drm/bochs/bochs_mm.c | |||
@@ -194,7 +194,7 @@ static struct ttm_tt *bochs_ttm_tt_create(struct ttm_bo_device *bdev, | |||
194 | return tt; | 194 | return tt; |
195 | } | 195 | } |
196 | 196 | ||
197 | struct ttm_bo_driver bochs_bo_driver = { | 197 | static struct ttm_bo_driver bochs_bo_driver = { |
198 | .ttm_tt_create = bochs_ttm_tt_create, | 198 | .ttm_tt_create = bochs_ttm_tt_create, |
199 | .ttm_tt_populate = ttm_pool_populate, | 199 | .ttm_tt_populate = ttm_pool_populate, |
200 | .ttm_tt_unpopulate = ttm_pool_unpopulate, | 200 | .ttm_tt_unpopulate = ttm_pool_unpopulate, |
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index a38db40ce990..f9802399cc0d 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | |||
@@ -1037,19 +1037,21 @@ static void dw_hdmi_phy_enable_svsret(struct dw_hdmi *hdmi, u8 enable) | |||
1037 | HDMI_PHY_CONF0_SVSRET_MASK); | 1037 | HDMI_PHY_CONF0_SVSRET_MASK); |
1038 | } | 1038 | } |
1039 | 1039 | ||
1040 | static void dw_hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, u8 enable) | 1040 | void dw_hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, u8 enable) |
1041 | { | 1041 | { |
1042 | hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, | 1042 | hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, |
1043 | HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET, | 1043 | HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET, |
1044 | HDMI_PHY_CONF0_GEN2_PDDQ_MASK); | 1044 | HDMI_PHY_CONF0_GEN2_PDDQ_MASK); |
1045 | } | 1045 | } |
1046 | EXPORT_SYMBOL_GPL(dw_hdmi_phy_gen2_pddq); | ||
1046 | 1047 | ||
1047 | static void dw_hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, u8 enable) | 1048 | void dw_hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, u8 enable) |
1048 | { | 1049 | { |
1049 | hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, | 1050 | hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, |
1050 | HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET, | 1051 | HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET, |
1051 | HDMI_PHY_CONF0_GEN2_TXPWRON_MASK); | 1052 | HDMI_PHY_CONF0_GEN2_TXPWRON_MASK); |
1052 | } | 1053 | } |
1054 | EXPORT_SYMBOL_GPL(dw_hdmi_phy_gen2_txpwron); | ||
1053 | 1055 | ||
1054 | static void dw_hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, u8 enable) | 1056 | static void dw_hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, u8 enable) |
1055 | { | 1057 | { |
@@ -1065,6 +1067,22 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable) | |||
1065 | HDMI_PHY_CONF0_SELDIPIF_MASK); | 1067 | HDMI_PHY_CONF0_SELDIPIF_MASK); |
1066 | } | 1068 | } |
1067 | 1069 | ||
1070 | void dw_hdmi_phy_reset(struct dw_hdmi *hdmi) | ||
1071 | { | ||
1072 | /* PHY reset. The reset signal is active high on Gen2 PHYs. */ | ||
1073 | hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_PHYRSTZ, HDMI_MC_PHYRSTZ); | ||
1074 | hdmi_writeb(hdmi, 0, HDMI_MC_PHYRSTZ); | ||
1075 | } | ||
1076 | EXPORT_SYMBOL_GPL(dw_hdmi_phy_reset); | ||
1077 | |||
1078 | void dw_hdmi_phy_i2c_set_addr(struct dw_hdmi *hdmi, u8 address) | ||
1079 | { | ||
1080 | hdmi_phy_test_clear(hdmi, 1); | ||
1081 | hdmi_writeb(hdmi, address, HDMI_PHY_I2CM_SLAVE_ADDR); | ||
1082 | hdmi_phy_test_clear(hdmi, 0); | ||
1083 | } | ||
1084 | EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_set_addr); | ||
1085 | |||
1068 | static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi) | 1086 | static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi) |
1069 | { | 1087 | { |
1070 | const struct dw_hdmi_phy_data *phy = hdmi->phy.data; | 1088 | const struct dw_hdmi_phy_data *phy = hdmi->phy.data; |
@@ -1203,16 +1221,11 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) | |||
1203 | if (phy->has_svsret) | 1221 | if (phy->has_svsret) |
1204 | dw_hdmi_phy_enable_svsret(hdmi, 1); | 1222 | dw_hdmi_phy_enable_svsret(hdmi, 1); |
1205 | 1223 | ||
1206 | /* PHY reset. The reset signal is active high on Gen2 PHYs. */ | 1224 | dw_hdmi_phy_reset(hdmi); |
1207 | hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_PHYRSTZ, HDMI_MC_PHYRSTZ); | ||
1208 | hdmi_writeb(hdmi, 0, HDMI_MC_PHYRSTZ); | ||
1209 | 1225 | ||
1210 | hdmi_writeb(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST); | 1226 | hdmi_writeb(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST); |
1211 | 1227 | ||
1212 | hdmi_phy_test_clear(hdmi, 1); | 1228 | dw_hdmi_phy_i2c_set_addr(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2); |
1213 | hdmi_writeb(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2, | ||
1214 | HDMI_PHY_I2CM_SLAVE_ADDR); | ||
1215 | hdmi_phy_test_clear(hdmi, 0); | ||
1216 | 1229 | ||
1217 | /* Write to the PHY as configured by the platform */ | 1230 | /* Write to the PHY as configured by the platform */ |
1218 | if (pdata->configure_phy) | 1231 | if (pdata->configure_phy) |
@@ -1251,15 +1264,16 @@ static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data) | |||
1251 | dw_hdmi_phy_power_off(hdmi); | 1264 | dw_hdmi_phy_power_off(hdmi); |
1252 | } | 1265 | } |
1253 | 1266 | ||
1254 | static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi, | 1267 | enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi, |
1255 | void *data) | 1268 | void *data) |
1256 | { | 1269 | { |
1257 | return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ? | 1270 | return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ? |
1258 | connector_status_connected : connector_status_disconnected; | 1271 | connector_status_connected : connector_status_disconnected; |
1259 | } | 1272 | } |
1273 | EXPORT_SYMBOL_GPL(dw_hdmi_phy_read_hpd); | ||
1260 | 1274 | ||
1261 | static void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data, | 1275 | void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data, |
1262 | bool force, bool disabled, bool rxsense) | 1276 | bool force, bool disabled, bool rxsense) |
1263 | { | 1277 | { |
1264 | u8 old_mask = hdmi->phy_mask; | 1278 | u8 old_mask = hdmi->phy_mask; |
1265 | 1279 | ||
@@ -1271,8 +1285,9 @@ static void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data, | |||
1271 | if (old_mask != hdmi->phy_mask) | 1285 | if (old_mask != hdmi->phy_mask) |
1272 | hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); | 1286 | hdmi_writeb(hdmi, hdmi->phy_mask, HDMI_PHY_MASK0); |
1273 | } | 1287 | } |
1288 | EXPORT_SYMBOL_GPL(dw_hdmi_phy_update_hpd); | ||
1274 | 1289 | ||
1275 | static void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data) | 1290 | void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data) |
1276 | { | 1291 | { |
1277 | /* | 1292 | /* |
1278 | * Configure the PHY RX SENSE and HPD interrupts polarities and clear | 1293 | * Configure the PHY RX SENSE and HPD interrupts polarities and clear |
@@ -1291,6 +1306,7 @@ static void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data) | |||
1291 | hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE), | 1306 | hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE), |
1292 | HDMI_IH_MUTE_PHY_STAT0); | 1307 | HDMI_IH_MUTE_PHY_STAT0); |
1293 | } | 1308 | } |
1309 | EXPORT_SYMBOL_GPL(dw_hdmi_phy_setup_hpd); | ||
1294 | 1310 | ||
1295 | static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = { | 1311 | static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = { |
1296 | .init = dw_hdmi_phy_init, | 1312 | .init = dw_hdmi_phy_init, |
@@ -1634,9 +1650,10 @@ static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi) | |||
1634 | * then write one of the FC registers several times. | 1650 | * then write one of the FC registers several times. |
1635 | * | 1651 | * |
1636 | * The number of iterations matters and depends on the HDMI TX revision | 1652 | * The number of iterations matters and depends on the HDMI TX revision |
1637 | * (and possibly on the platform). So far only i.MX6Q (v1.30a) and | 1653 | * (and possibly on the platform). So far i.MX6Q (v1.30a), i.MX6DL |
1638 | * i.MX6DL (v1.31a) have been identified as needing the workaround, with | 1654 | * (v1.31a) and multiple Allwinner SoCs (v1.32a) have been identified |
1639 | * 4 and 1 iterations respectively. | 1655 | * as needing the workaround, with 4 iterations for v1.30a and 1 |
1656 | * iteration for others. | ||
1640 | */ | 1657 | */ |
1641 | 1658 | ||
1642 | switch (hdmi->version) { | 1659 | switch (hdmi->version) { |
@@ -1644,6 +1661,7 @@ static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi) | |||
1644 | count = 4; | 1661 | count = 4; |
1645 | break; | 1662 | break; |
1646 | case 0x131a: | 1663 | case 0x131a: |
1664 | case 0x132a: | ||
1647 | count = 1; | 1665 | count = 1; |
1648 | break; | 1666 | break; |
1649 | default: | 1667 | default: |
@@ -2525,8 +2543,6 @@ __dw_hdmi_probe(struct platform_device *pdev, | |||
2525 | if (hdmi->i2c) | 2543 | if (hdmi->i2c) |
2526 | dw_hdmi_i2c_init(hdmi); | 2544 | dw_hdmi_i2c_init(hdmi); |
2527 | 2545 | ||
2528 | platform_set_drvdata(pdev, hdmi); | ||
2529 | |||
2530 | return hdmi; | 2546 | return hdmi; |
2531 | 2547 | ||
2532 | err_iahb: | 2548 | err_iahb: |
@@ -2576,25 +2592,23 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi) | |||
2576 | /* ----------------------------------------------------------------------------- | 2592 | /* ----------------------------------------------------------------------------- |
2577 | * Probe/remove API, used from platforms based on the DRM bridge API. | 2593 | * Probe/remove API, used from platforms based on the DRM bridge API. |
2578 | */ | 2594 | */ |
2579 | int dw_hdmi_probe(struct platform_device *pdev, | 2595 | struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, |
2580 | const struct dw_hdmi_plat_data *plat_data) | 2596 | const struct dw_hdmi_plat_data *plat_data) |
2581 | { | 2597 | { |
2582 | struct dw_hdmi *hdmi; | 2598 | struct dw_hdmi *hdmi; |
2583 | 2599 | ||
2584 | hdmi = __dw_hdmi_probe(pdev, plat_data); | 2600 | hdmi = __dw_hdmi_probe(pdev, plat_data); |
2585 | if (IS_ERR(hdmi)) | 2601 | if (IS_ERR(hdmi)) |
2586 | return PTR_ERR(hdmi); | 2602 | return hdmi; |
2587 | 2603 | ||
2588 | drm_bridge_add(&hdmi->bridge); | 2604 | drm_bridge_add(&hdmi->bridge); |
2589 | 2605 | ||
2590 | return 0; | 2606 | return hdmi; |
2591 | } | 2607 | } |
2592 | EXPORT_SYMBOL_GPL(dw_hdmi_probe); | 2608 | EXPORT_SYMBOL_GPL(dw_hdmi_probe); |
2593 | 2609 | ||
2594 | void dw_hdmi_remove(struct platform_device *pdev) | 2610 | void dw_hdmi_remove(struct dw_hdmi *hdmi) |
2595 | { | 2611 | { |
2596 | struct dw_hdmi *hdmi = platform_get_drvdata(pdev); | ||
2597 | |||
2598 | drm_bridge_remove(&hdmi->bridge); | 2612 | drm_bridge_remove(&hdmi->bridge); |
2599 | 2613 | ||
2600 | __dw_hdmi_remove(hdmi); | 2614 | __dw_hdmi_remove(hdmi); |
@@ -2604,31 +2618,30 @@ EXPORT_SYMBOL_GPL(dw_hdmi_remove); | |||
2604 | /* ----------------------------------------------------------------------------- | 2618 | /* ----------------------------------------------------------------------------- |
2605 | * Bind/unbind API, used from platforms based on the component framework. | 2619 | * Bind/unbind API, used from platforms based on the component framework. |
2606 | */ | 2620 | */ |
2607 | int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, | 2621 | struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev, |
2608 | const struct dw_hdmi_plat_data *plat_data) | 2622 | struct drm_encoder *encoder, |
2623 | const struct dw_hdmi_plat_data *plat_data) | ||
2609 | { | 2624 | { |
2610 | struct dw_hdmi *hdmi; | 2625 | struct dw_hdmi *hdmi; |
2611 | int ret; | 2626 | int ret; |
2612 | 2627 | ||
2613 | hdmi = __dw_hdmi_probe(pdev, plat_data); | 2628 | hdmi = __dw_hdmi_probe(pdev, plat_data); |
2614 | if (IS_ERR(hdmi)) | 2629 | if (IS_ERR(hdmi)) |
2615 | return PTR_ERR(hdmi); | 2630 | return hdmi; |
2616 | 2631 | ||
2617 | ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL); | 2632 | ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL); |
2618 | if (ret) { | 2633 | if (ret) { |
2619 | dw_hdmi_remove(pdev); | 2634 | dw_hdmi_remove(hdmi); |
2620 | DRM_ERROR("Failed to initialize bridge with drm\n"); | 2635 | DRM_ERROR("Failed to initialize bridge with drm\n"); |
2621 | return ret; | 2636 | return ERR_PTR(ret); |
2622 | } | 2637 | } |
2623 | 2638 | ||
2624 | return 0; | 2639 | return hdmi; |
2625 | } | 2640 | } |
2626 | EXPORT_SYMBOL_GPL(dw_hdmi_bind); | 2641 | EXPORT_SYMBOL_GPL(dw_hdmi_bind); |
2627 | 2642 | ||
2628 | void dw_hdmi_unbind(struct device *dev) | 2643 | void dw_hdmi_unbind(struct dw_hdmi *hdmi) |
2629 | { | 2644 | { |
2630 | struct dw_hdmi *hdmi = dev_get_drvdata(dev); | ||
2631 | |||
2632 | __dw_hdmi_remove(hdmi); | 2645 | __dw_hdmi_remove(hdmi); |
2633 | } | 2646 | } |
2634 | EXPORT_SYMBOL_GPL(dw_hdmi_unbind); | 2647 | EXPORT_SYMBOL_GPL(dw_hdmi_unbind); |
diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c index 4c62dff14893..5a81e1b4c076 100644 --- a/drivers/gpu/drm/drm_blend.c +++ b/drivers/gpu/drm/drm_blend.c | |||
@@ -88,15 +88,17 @@ | |||
88 | * On top of this basic transformation additional properties can be exposed by | 88 | * On top of this basic transformation additional properties can be exposed by |
89 | * the driver: | 89 | * the driver: |
90 | * | 90 | * |
91 | * - Rotation is set up with drm_plane_create_rotation_property(). It adds a | 91 | * rotation: |
92 | * rotation and reflection step between the source and destination rectangles. | 92 | * Rotation is set up with drm_plane_create_rotation_property(). It adds a |
93 | * Without this property the rectangle is only scaled, but not rotated or | 93 | * rotation and reflection step between the source and destination rectangles. |
94 | * reflected. | 94 | * Without this property the rectangle is only scaled, but not rotated or |
95 | * reflected. | ||
95 | * | 96 | * |
96 | * - Z position is set up with drm_plane_create_zpos_immutable_property() and | 97 | * zpos: |
97 | * drm_plane_create_zpos_property(). It controls the visibility of overlapping | 98 | * Z position is set up with drm_plane_create_zpos_immutable_property() and |
98 | * planes. Without this property the primary plane is always below the cursor | 99 | * drm_plane_create_zpos_property(). It controls the visibility of overlapping |
99 | * plane, and ordering between all other planes is undefined. | 100 | * planes. Without this property the primary plane is always below the cursor |
101 | * plane, and ordering between all other planes is undefined. | ||
100 | * | 102 | * |
101 | * Note that all the property extensions described here apply either to the | 103 | * Note that all the property extensions described here apply either to the |
102 | * plane or the CRTC (e.g. for the background color, which currently is not | 104 | * plane or the CRTC (e.g. for the background color, which currently is not |
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 16b9c3810af2..b3cde897cd80 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c | |||
@@ -849,13 +849,13 @@ DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list) | |||
849 | * | 849 | * |
850 | * The value of this property can be one of the following: | 850 | * The value of this property can be one of the following: |
851 | * | 851 | * |
852 | * - DRM_MODE_CONTENT_PROTECTION_UNDESIRED = 0 | 852 | * DRM_MODE_CONTENT_PROTECTION_UNDESIRED = 0 |
853 | * The link is not protected, content is transmitted in the clear. | 853 | * The link is not protected, content is transmitted in the clear. |
854 | * - DRM_MODE_CONTENT_PROTECTION_DESIRED = 1 | 854 | * DRM_MODE_CONTENT_PROTECTION_DESIRED = 1 |
855 | * Userspace has requested content protection, but the link is not | 855 | * Userspace has requested content protection, but the link is not |
856 | * currently protected. When in this state, kernel should enable | 856 | * currently protected. When in this state, kernel should enable |
857 | * Content Protection as soon as possible. | 857 | * Content Protection as soon as possible. |
858 | * - DRM_MODE_CONTENT_PROTECTION_ENABLED = 2 | 858 | * DRM_MODE_CONTENT_PROTECTION_ENABLED = 2 |
859 | * Userspace has requested content protection, and the link is | 859 | * Userspace has requested content protection, and the link is |
860 | * protected. Only the driver can set the property to this value. | 860 | * protected. Only the driver can set the property to this value. |
861 | * If userspace attempts to set to ENABLED, kernel will return | 861 | * If userspace attempts to set to ENABLED, kernel will return |
@@ -889,7 +889,31 @@ DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list) | |||
889 | * INPUT_PROP_DIRECT) will still map 1:1 to the actual LCD panel | 889 | * INPUT_PROP_DIRECT) will still map 1:1 to the actual LCD panel |
890 | * coordinates, so if userspace rotates the picture to adjust for | 890 | * coordinates, so if userspace rotates the picture to adjust for |
891 | * the orientation it must also apply the same transformation to the | 891 | * the orientation it must also apply the same transformation to the |
892 | * touchscreen input coordinates. | 892 | * touchscreen input coordinates. This property is initialized by calling |
893 | * drm_connector_init_panel_orientation_property(). | ||
894 | * | ||
895 | * scaling mode: | ||
896 | * This property defines how a non-native mode is upscaled to the native | ||
897 | * mode of an LCD panel: | ||
898 | * | ||
899 | * None: | ||
900 | * No upscaling happens, scaling is left to the panel. Not all | ||
901 | * drivers expose this mode. | ||
902 | * Full: | ||
903 | * The output is upscaled to the full resolution of the panel, | ||
904 | * ignoring the aspect ratio. | ||
905 | * Center: | ||
906 | * No upscaling happens, the output is centered within the native | ||
907 | * resolution the panel. | ||
908 | * Full aspect: | ||
909 | * The output is upscaled to maximize either the width or height | ||
910 | * while retaining the aspect ratio. | ||
911 | * | ||
912 | * This property should be set up by calling | ||
913 | * drm_connector_attach_scaling_mode_property(). Note that drivers | ||
914 | * can also expose this property to external outputs, in which case they | ||
915 | * must support "None", which should be the default (since external screens | ||
916 | * have a built-in scaler). | ||
893 | */ | 917 | */ |
894 | 918 | ||
895 | int drm_connector_create_standard_properties(struct drm_device *dev) | 919 | int drm_connector_create_standard_properties(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 36df7df5fe1a..6fac4129e6a2 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c | |||
@@ -1082,10 +1082,12 @@ static bool drm_dp_port_setup_pdt(struct drm_dp_mst_port *port) | |||
1082 | lct = drm_dp_calculate_rad(port, rad); | 1082 | lct = drm_dp_calculate_rad(port, rad); |
1083 | 1083 | ||
1084 | port->mstb = drm_dp_add_mst_branch_device(lct, rad); | 1084 | port->mstb = drm_dp_add_mst_branch_device(lct, rad); |
1085 | port->mstb->mgr = port->mgr; | 1085 | if (port->mstb) { |
1086 | port->mstb->port_parent = port; | 1086 | port->mstb->mgr = port->mgr; |
1087 | port->mstb->port_parent = port; | ||
1087 | 1088 | ||
1088 | send_link = true; | 1089 | send_link = true; |
1090 | } | ||
1089 | break; | 1091 | break; |
1090 | } | 1092 | } |
1091 | return send_link; | 1093 | return send_link; |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index b1cb2627548f..a797bbf1cab8 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -2083,6 +2083,8 @@ drm_mode_std(struct drm_connector *connector, struct edid *edid, | |||
2083 | if (hsize == 1366 && vsize == 768 && vrefresh_rate == 60) { | 2083 | if (hsize == 1366 && vsize == 768 && vrefresh_rate == 60) { |
2084 | mode = drm_cvt_mode(dev, 1366, 768, vrefresh_rate, 0, 0, | 2084 | mode = drm_cvt_mode(dev, 1366, 768, vrefresh_rate, 0, 0, |
2085 | false); | 2085 | false); |
2086 | if (!mode) | ||
2087 | return NULL; | ||
2086 | mode->hdisplay = 1366; | 2088 | mode->hdisplay = 1366; |
2087 | mode->hsync_start = mode->hsync_start - 1; | 2089 | mode->hsync_start = mode->hsync_start - 1; |
2088 | mode->hsync_end = mode->hsync_end - 1; | 2090 | mode->hsync_end = mode->hsync_end - 1; |
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 01f8d9481211..4975ba9a7bc8 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
@@ -98,7 +98,7 @@ drm_gem_init(struct drm_device *dev) | |||
98 | struct drm_vma_offset_manager *vma_offset_manager; | 98 | struct drm_vma_offset_manager *vma_offset_manager; |
99 | 99 | ||
100 | mutex_init(&dev->object_name_lock); | 100 | mutex_init(&dev->object_name_lock); |
101 | idr_init(&dev->object_name_idr); | 101 | idr_init_base(&dev->object_name_idr, 1); |
102 | 102 | ||
103 | vma_offset_manager = kzalloc(sizeof(*vma_offset_manager), GFP_KERNEL); | 103 | vma_offset_manager = kzalloc(sizeof(*vma_offset_manager), GFP_KERNEL); |
104 | if (!vma_offset_manager) { | 104 | if (!vma_offset_manager) { |
@@ -776,7 +776,7 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data, | |||
776 | void | 776 | void |
777 | drm_gem_open(struct drm_device *dev, struct drm_file *file_private) | 777 | drm_gem_open(struct drm_device *dev, struct drm_file *file_private) |
778 | { | 778 | { |
779 | idr_init(&file_private->object_idr); | 779 | idr_init_base(&file_private->object_idr, 1); |
780 | spin_lock_init(&file_private->table_lock); | 780 | spin_lock_init(&file_private->table_lock); |
781 | } | 781 | } |
782 | 782 | ||
diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c index 1402c0e71b03..d345563fdff3 100644 --- a/drivers/gpu/drm/drm_lease.c +++ b/drivers/gpu/drm/drm_lease.c | |||
@@ -44,7 +44,7 @@ EXPORT_SYMBOL(drm_lease_owner); | |||
44 | /** | 44 | /** |
45 | * _drm_find_lessee - find lessee by id (idr_mutex held) | 45 | * _drm_find_lessee - find lessee by id (idr_mutex held) |
46 | * @master: drm_master of lessor | 46 | * @master: drm_master of lessor |
47 | * @id: lessee_id | 47 | * @lessee_id: id |
48 | * | 48 | * |
49 | * RETURN: | 49 | * RETURN: |
50 | * | 50 | * |
@@ -101,7 +101,7 @@ static bool _drm_has_leased(struct drm_master *master, int id) | |||
101 | 101 | ||
102 | /** | 102 | /** |
103 | * _drm_lease_held - check drm_mode_object lease status (idr_mutex held) | 103 | * _drm_lease_held - check drm_mode_object lease status (idr_mutex held) |
104 | * @master: the drm_master | 104 | * @file_priv: the master drm_file |
105 | * @id: the object id | 105 | * @id: the object id |
106 | * | 106 | * |
107 | * Checks if the specified master holds a lease on the object. Return | 107 | * Checks if the specified master holds a lease on the object. Return |
@@ -121,7 +121,7 @@ EXPORT_SYMBOL(_drm_lease_held); | |||
121 | 121 | ||
122 | /** | 122 | /** |
123 | * drm_lease_held - check drm_mode_object lease status (idr_mutex not held) | 123 | * drm_lease_held - check drm_mode_object lease status (idr_mutex not held) |
124 | * @master: the drm_master | 124 | * @file_priv: the master drm_file |
125 | * @id: the object id | 125 | * @id: the object id |
126 | * | 126 | * |
127 | * Checks if the specified master holds a lease on the object. Return | 127 | * Checks if the specified master holds a lease on the object. Return |
@@ -149,7 +149,7 @@ EXPORT_SYMBOL(drm_lease_held); | |||
149 | /** | 149 | /** |
150 | * drm_lease_filter_crtcs - restricted crtc set to leased values (idr_mutex not held) | 150 | * drm_lease_filter_crtcs - restricted crtc set to leased values (idr_mutex not held) |
151 | * @file_priv: requestor file | 151 | * @file_priv: requestor file |
152 | * @crtcs: bitmask of crtcs to check | 152 | * @crtcs_in: bitmask of crtcs to check |
153 | * | 153 | * |
154 | * Reconstructs a crtc mask based on the crtcs which are visible | 154 | * Reconstructs a crtc mask based on the crtcs which are visible |
155 | * through the specified file. | 155 | * through the specified file. |
@@ -305,7 +305,7 @@ void drm_lease_destroy(struct drm_master *master) | |||
305 | 305 | ||
306 | /** | 306 | /** |
307 | * _drm_lease_revoke - revoke access to all leased objects (idr_mutex held) | 307 | * _drm_lease_revoke - revoke access to all leased objects (idr_mutex held) |
308 | * @master: the master losing its lease | 308 | * @top: the master losing its lease |
309 | */ | 309 | */ |
310 | static void _drm_lease_revoke(struct drm_master *top) | 310 | static void _drm_lease_revoke(struct drm_master *top) |
311 | { | 311 | { |
@@ -482,7 +482,7 @@ out_free_objects: | |||
482 | * drm_mode_create_lease_ioctl - create a new lease | 482 | * drm_mode_create_lease_ioctl - create a new lease |
483 | * @dev: the drm device | 483 | * @dev: the drm device |
484 | * @data: pointer to struct drm_mode_create_lease | 484 | * @data: pointer to struct drm_mode_create_lease |
485 | * @file_priv: the file being manipulated | 485 | * @lessor_priv: the file being manipulated |
486 | * | 486 | * |
487 | * The master associated with the specified file will have a lease | 487 | * The master associated with the specified file will have a lease |
488 | * created containing the objects specified in the ioctl structure. | 488 | * created containing the objects specified in the ioctl structure. |
@@ -662,7 +662,7 @@ int drm_mode_list_lessees_ioctl(struct drm_device *dev, | |||
662 | * drm_mode_get_lease_ioctl - list leased objects | 662 | * drm_mode_get_lease_ioctl - list leased objects |
663 | * @dev: the drm device | 663 | * @dev: the drm device |
664 | * @data: pointer to struct drm_mode_get_lease | 664 | * @data: pointer to struct drm_mode_get_lease |
665 | * @file_priv: the file being manipulated | 665 | * @lessee_priv: the file being manipulated |
666 | * | 666 | * |
667 | * Return the list of leased objects for the specified lessee | 667 | * Return the list of leased objects for the specified lessee |
668 | */ | 668 | */ |
@@ -722,7 +722,7 @@ int drm_mode_get_lease_ioctl(struct drm_device *dev, | |||
722 | * drm_mode_revoke_lease_ioctl - revoke lease | 722 | * drm_mode_revoke_lease_ioctl - revoke lease |
723 | * @dev: the drm device | 723 | * @dev: the drm device |
724 | * @data: pointer to struct drm_mode_revoke_lease | 724 | * @data: pointer to struct drm_mode_revoke_lease |
725 | * @file_priv: the file being manipulated | 725 | * @lessor_priv: the file being manipulated |
726 | * | 726 | * |
727 | * This removes all of the objects from the lease without | 727 | * This removes all of the objects from the lease without |
728 | * actually getting rid of the lease itself; that way all | 728 | * actually getting rid of the lease itself; that way all |
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index c397b523c945..5a8033fda4e3 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c | |||
@@ -1346,9 +1346,9 @@ EXPORT_SYMBOL(drm_mode_connector_list_update); | |||
1346 | * modeline in fb_mode_option will be parsed instead. | 1346 | * modeline in fb_mode_option will be parsed instead. |
1347 | * | 1347 | * |
1348 | * This uses the same parameters as the fb modedb.c, except for an extra | 1348 | * This uses the same parameters as the fb modedb.c, except for an extra |
1349 | * force-enable, force-enable-digital and force-disable bit at the end: | 1349 | * force-enable, force-enable-digital and force-disable bit at the end:: |
1350 | * | 1350 | * |
1351 | * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd] | 1351 | * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd] |
1352 | * | 1352 | * |
1353 | * The intermediate drm_cmdline_mode structure is required to store additional | 1353 | * The intermediate drm_cmdline_mode structure is required to store additional |
1354 | * options from the command line modline like the force-enable/disable flag. | 1354 | * options from the command line modline like the force-enable/disable flag. |
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c index 9d3f6b70812c..6c327fdbaaee 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c | |||
@@ -34,6 +34,20 @@ static const struct drm_encoder_funcs drm_simple_kms_encoder_funcs = { | |||
34 | .destroy = drm_encoder_cleanup, | 34 | .destroy = drm_encoder_cleanup, |
35 | }; | 35 | }; |
36 | 36 | ||
37 | static enum drm_mode_status | ||
38 | drm_simple_kms_crtc_mode_valid(struct drm_crtc *crtc, | ||
39 | const struct drm_display_mode *mode) | ||
40 | { | ||
41 | struct drm_simple_display_pipe *pipe; | ||
42 | |||
43 | pipe = container_of(crtc, struct drm_simple_display_pipe, crtc); | ||
44 | if (!pipe->funcs || !pipe->funcs->mode_valid) | ||
45 | /* Anything goes */ | ||
46 | return MODE_OK; | ||
47 | |||
48 | return pipe->funcs->mode_valid(crtc, mode); | ||
49 | } | ||
50 | |||
37 | static int drm_simple_kms_crtc_check(struct drm_crtc *crtc, | 51 | static int drm_simple_kms_crtc_check(struct drm_crtc *crtc, |
38 | struct drm_crtc_state *state) | 52 | struct drm_crtc_state *state) |
39 | { | 53 | { |
@@ -72,6 +86,7 @@ static void drm_simple_kms_crtc_disable(struct drm_crtc *crtc, | |||
72 | } | 86 | } |
73 | 87 | ||
74 | static const struct drm_crtc_helper_funcs drm_simple_kms_crtc_helper_funcs = { | 88 | static const struct drm_crtc_helper_funcs drm_simple_kms_crtc_helper_funcs = { |
89 | .mode_valid = drm_simple_kms_crtc_mode_valid, | ||
75 | .atomic_check = drm_simple_kms_crtc_check, | 90 | .atomic_check = drm_simple_kms_crtc_check, |
76 | .atomic_enable = drm_simple_kms_crtc_enable, | 91 | .atomic_enable = drm_simple_kms_crtc_enable, |
77 | .atomic_disable = drm_simple_kms_crtc_disable, | 92 | .atomic_disable = drm_simple_kms_crtc_disable, |
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 0b7b0d1ad2d5..d4f4ce484529 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c | |||
@@ -546,7 +546,7 @@ err_put_fd: | |||
546 | void | 546 | void |
547 | drm_syncobj_open(struct drm_file *file_private) | 547 | drm_syncobj_open(struct drm_file *file_private) |
548 | { | 548 | { |
549 | idr_init(&file_private->syncobj_idr); | 549 | idr_init_base(&file_private->syncobj_idr, 1); |
550 | spin_lock_init(&file_private->syncobj_table_lock); | 550 | spin_lock_init(&file_private->syncobj_table_lock); |
551 | } | 551 | } |
552 | 552 | ||
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c index b62763aa8706..fe6becdcc29e 100644 --- a/drivers/gpu/drm/imx/dw_hdmi-imx.c +++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c | |||
@@ -25,6 +25,7 @@ | |||
25 | struct imx_hdmi { | 25 | struct imx_hdmi { |
26 | struct device *dev; | 26 | struct device *dev; |
27 | struct drm_encoder encoder; | 27 | struct drm_encoder encoder; |
28 | struct dw_hdmi *hdmi; | ||
28 | struct regmap *regmap; | 29 | struct regmap *regmap; |
29 | }; | 30 | }; |
30 | 31 | ||
@@ -239,14 +240,18 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master, | |||
239 | drm_encoder_init(drm, encoder, &dw_hdmi_imx_encoder_funcs, | 240 | drm_encoder_init(drm, encoder, &dw_hdmi_imx_encoder_funcs, |
240 | DRM_MODE_ENCODER_TMDS, NULL); | 241 | DRM_MODE_ENCODER_TMDS, NULL); |
241 | 242 | ||
242 | ret = dw_hdmi_bind(pdev, encoder, plat_data); | 243 | platform_set_drvdata(pdev, hdmi); |
244 | |||
245 | hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); | ||
243 | 246 | ||
244 | /* | 247 | /* |
245 | * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), | 248 | * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), |
246 | * which would have called the encoder cleanup. Do it manually. | 249 | * which would have called the encoder cleanup. Do it manually. |
247 | */ | 250 | */ |
248 | if (ret) | 251 | if (IS_ERR(hdmi->hdmi)) { |
252 | ret = PTR_ERR(hdmi->hdmi); | ||
249 | drm_encoder_cleanup(encoder); | 253 | drm_encoder_cleanup(encoder); |
254 | } | ||
250 | 255 | ||
251 | return ret; | 256 | return ret; |
252 | } | 257 | } |
@@ -254,7 +259,9 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master, | |||
254 | static void dw_hdmi_imx_unbind(struct device *dev, struct device *master, | 259 | static void dw_hdmi_imx_unbind(struct device *dev, struct device *master, |
255 | void *data) | 260 | void *data) |
256 | { | 261 | { |
257 | return dw_hdmi_unbind(dev); | 262 | struct imx_hdmi *hdmi = dev_get_drvdata(dev); |
263 | |||
264 | dw_hdmi_unbind(hdmi->hdmi); | ||
258 | } | 265 | } |
259 | 266 | ||
260 | static const struct component_ops dw_hdmi_imx_ops = { | 267 | static const struct component_ops dw_hdmi_imx_ops = { |
diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c index 17de3afd98f6..d49af17310c9 100644 --- a/drivers/gpu/drm/meson/meson_dw_hdmi.c +++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c | |||
@@ -140,6 +140,7 @@ struct meson_dw_hdmi { | |||
140 | struct clk *venci_clk; | 140 | struct clk *venci_clk; |
141 | struct regulator *hdmi_supply; | 141 | struct regulator *hdmi_supply; |
142 | u32 irq_stat; | 142 | u32 irq_stat; |
143 | struct dw_hdmi *hdmi; | ||
143 | }; | 144 | }; |
144 | #define encoder_to_meson_dw_hdmi(x) \ | 145 | #define encoder_to_meson_dw_hdmi(x) \ |
145 | container_of(x, struct meson_dw_hdmi, encoder) | 146 | container_of(x, struct meson_dw_hdmi, encoder) |
@@ -302,7 +303,7 @@ static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi, | |||
302 | } | 303 | } |
303 | } | 304 | } |
304 | 305 | ||
305 | static inline void dw_hdmi_phy_reset(struct meson_dw_hdmi *dw_hdmi) | 306 | static inline void meson_dw_hdmi_phy_reset(struct meson_dw_hdmi *dw_hdmi) |
306 | { | 307 | { |
307 | struct meson_drm *priv = dw_hdmi->priv; | 308 | struct meson_drm *priv = dw_hdmi->priv; |
308 | 309 | ||
@@ -409,9 +410,9 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, | |||
409 | msleep(100); | 410 | msleep(100); |
410 | 411 | ||
411 | /* Reset PHY 3 times in a row */ | 412 | /* Reset PHY 3 times in a row */ |
412 | dw_hdmi_phy_reset(dw_hdmi); | 413 | meson_dw_hdmi_phy_reset(dw_hdmi); |
413 | dw_hdmi_phy_reset(dw_hdmi); | 414 | meson_dw_hdmi_phy_reset(dw_hdmi); |
414 | dw_hdmi_phy_reset(dw_hdmi); | 415 | meson_dw_hdmi_phy_reset(dw_hdmi); |
415 | 416 | ||
416 | /* Temporary Disable VENC video stream */ | 417 | /* Temporary Disable VENC video stream */ |
417 | if (priv->venc.hdmi_use_enci) | 418 | if (priv->venc.hdmi_use_enci) |
@@ -878,9 +879,12 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master, | |||
878 | dw_plat_data->input_bus_format = MEDIA_BUS_FMT_YUV8_1X24; | 879 | dw_plat_data->input_bus_format = MEDIA_BUS_FMT_YUV8_1X24; |
879 | dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709; | 880 | dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709; |
880 | 881 | ||
881 | ret = dw_hdmi_bind(pdev, encoder, &meson_dw_hdmi->dw_plat_data); | 882 | platform_set_drvdata(pdev, meson_dw_hdmi); |
882 | if (ret) | 883 | |
883 | return ret; | 884 | meson_dw_hdmi->hdmi = dw_hdmi_bind(pdev, encoder, |
885 | &meson_dw_hdmi->dw_plat_data); | ||
886 | if (IS_ERR(meson_dw_hdmi->hdmi)) | ||
887 | return PTR_ERR(meson_dw_hdmi->hdmi); | ||
884 | 888 | ||
885 | DRM_DEBUG_DRIVER("HDMI controller initialized\n"); | 889 | DRM_DEBUG_DRIVER("HDMI controller initialized\n"); |
886 | 890 | ||
@@ -890,7 +894,9 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master, | |||
890 | static void meson_dw_hdmi_unbind(struct device *dev, struct device *master, | 894 | static void meson_dw_hdmi_unbind(struct device *dev, struct device *master, |
891 | void *data) | 895 | void *data) |
892 | { | 896 | { |
893 | dw_hdmi_unbind(dev); | 897 | struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev); |
898 | |||
899 | dw_hdmi_unbind(meson_dw_hdmi->hdmi); | ||
894 | } | 900 | } |
895 | 901 | ||
896 | static const struct component_ops meson_dw_hdmi_ops = { | 902 | static const struct component_ops meson_dw_hdmi_ops = { |
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c b/drivers/gpu/drm/omapdrm/displays/panel-dpi.c index efff6dbbb86f..48a03f55610a 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-dpi.c | |||
@@ -87,11 +87,7 @@ static int panel_dpi_enable(struct omap_dss_device *dssdev) | |||
87 | } | 87 | } |
88 | 88 | ||
89 | gpiod_set_value_cansleep(ddata->enable_gpio, 1); | 89 | gpiod_set_value_cansleep(ddata->enable_gpio, 1); |
90 | 90 | backlight_enable(ddata->backlight); | |
91 | if (ddata->backlight) { | ||
92 | ddata->backlight->props.power = FB_BLANK_UNBLANK; | ||
93 | backlight_update_status(ddata->backlight); | ||
94 | } | ||
95 | 91 | ||
96 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | 92 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; |
97 | 93 | ||
@@ -106,10 +102,7 @@ static void panel_dpi_disable(struct omap_dss_device *dssdev) | |||
106 | if (!omapdss_device_is_enabled(dssdev)) | 102 | if (!omapdss_device_is_enabled(dssdev)) |
107 | return; | 103 | return; |
108 | 104 | ||
109 | if (ddata->backlight) { | 105 | backlight_disable(ddata->backlight); |
110 | ddata->backlight->props.power = FB_BLANK_POWERDOWN; | ||
111 | backlight_update_status(ddata->backlight); | ||
112 | } | ||
113 | 106 | ||
114 | gpiod_set_value_cansleep(ddata->enable_gpio, 0); | 107 | gpiod_set_value_cansleep(ddata->enable_gpio, 0); |
115 | regulator_disable(ddata->vcc_supply); | 108 | regulator_disable(ddata->vcc_supply); |
@@ -164,7 +157,6 @@ static int panel_dpi_probe_of(struct platform_device *pdev) | |||
164 | { | 157 | { |
165 | struct panel_drv_data *ddata = platform_get_drvdata(pdev); | 158 | struct panel_drv_data *ddata = platform_get_drvdata(pdev); |
166 | struct device_node *node = pdev->dev.of_node; | 159 | struct device_node *node = pdev->dev.of_node; |
167 | struct device_node *bl_node; | ||
168 | struct omap_dss_device *in; | 160 | struct omap_dss_device *in; |
169 | int r; | 161 | int r; |
170 | struct display_timing timing; | 162 | struct display_timing timing; |
@@ -190,19 +182,15 @@ static int panel_dpi_probe_of(struct platform_device *pdev) | |||
190 | if (IS_ERR(ddata->vcc_supply)) | 182 | if (IS_ERR(ddata->vcc_supply)) |
191 | return PTR_ERR(ddata->vcc_supply); | 183 | return PTR_ERR(ddata->vcc_supply); |
192 | 184 | ||
193 | bl_node = of_parse_phandle(node, "backlight", 0); | 185 | ddata->backlight = devm_of_find_backlight(&pdev->dev); |
194 | if (bl_node) { | ||
195 | ddata->backlight = of_find_backlight_by_node(bl_node); | ||
196 | of_node_put(bl_node); | ||
197 | 186 | ||
198 | if (!ddata->backlight) | 187 | if (IS_ERR(ddata->backlight)) |
199 | return -EPROBE_DEFER; | 188 | return PTR_ERR(ddata->backlight); |
200 | } | ||
201 | 189 | ||
202 | r = of_get_display_timing(node, "panel-timing", &timing); | 190 | r = of_get_display_timing(node, "panel-timing", &timing); |
203 | if (r) { | 191 | if (r) { |
204 | dev_err(&pdev->dev, "failed to get video timing\n"); | 192 | dev_err(&pdev->dev, "failed to get video timing\n"); |
205 | goto error_free_backlight; | 193 | return r; |
206 | } | 194 | } |
207 | 195 | ||
208 | videomode_from_timing(&timing, &ddata->vm); | 196 | videomode_from_timing(&timing, &ddata->vm); |
@@ -210,19 +198,12 @@ static int panel_dpi_probe_of(struct platform_device *pdev) | |||
210 | in = omapdss_of_find_source_for_first_ep(node); | 198 | in = omapdss_of_find_source_for_first_ep(node); |
211 | if (IS_ERR(in)) { | 199 | if (IS_ERR(in)) { |
212 | dev_err(&pdev->dev, "failed to find video source\n"); | 200 | dev_err(&pdev->dev, "failed to find video source\n"); |
213 | r = PTR_ERR(in); | 201 | return PTR_ERR(in); |
214 | goto error_free_backlight; | ||
215 | } | 202 | } |
216 | 203 | ||
217 | ddata->in = in; | 204 | ddata->in = in; |
218 | 205 | ||
219 | return 0; | 206 | return 0; |
220 | |||
221 | error_free_backlight: | ||
222 | if (ddata->backlight) | ||
223 | put_device(&ddata->backlight->dev); | ||
224 | |||
225 | return r; | ||
226 | } | 207 | } |
227 | 208 | ||
228 | static int panel_dpi_probe(struct platform_device *pdev) | 209 | static int panel_dpi_probe(struct platform_device *pdev) |
@@ -277,9 +258,6 @@ static int __exit panel_dpi_remove(struct platform_device *pdev) | |||
277 | 258 | ||
278 | omap_dss_put_device(in); | 259 | omap_dss_put_device(in); |
279 | 260 | ||
280 | if (ddata->backlight) | ||
281 | put_device(&ddata->backlight->dev); | ||
282 | |||
283 | return 0; | 261 | return 0; |
284 | } | 262 | } |
285 | 263 | ||
diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c index 6ba93449fcfb..57df39b5c589 100644 --- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c +++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c | |||
@@ -45,8 +45,7 @@ static int innolux_panel_disable(struct drm_panel *panel) | |||
45 | if (!innolux->enabled) | 45 | if (!innolux->enabled) |
46 | return 0; | 46 | return 0; |
47 | 47 | ||
48 | innolux->backlight->props.power = FB_BLANK_POWERDOWN; | 48 | backlight_disable(innolux->backlight); |
49 | backlight_update_status(innolux->backlight); | ||
50 | 49 | ||
51 | err = mipi_dsi_dcs_set_display_off(innolux->link); | 50 | err = mipi_dsi_dcs_set_display_off(innolux->link); |
52 | if (err < 0) | 51 | if (err < 0) |
@@ -151,8 +150,7 @@ static int innolux_panel_enable(struct drm_panel *panel) | |||
151 | if (innolux->enabled) | 150 | if (innolux->enabled) |
152 | return 0; | 151 | return 0; |
153 | 152 | ||
154 | innolux->backlight->props.power = FB_BLANK_UNBLANK; | 153 | ret = backlight_enable(innolux->backlight); |
155 | ret = backlight_update_status(innolux->backlight); | ||
156 | if (ret) { | 154 | if (ret) { |
157 | DRM_DEV_ERROR(panel->drm->dev, | 155 | DRM_DEV_ERROR(panel->drm->dev, |
158 | "Failed to enable backlight %d\n", ret); | 156 | "Failed to enable backlight %d\n", ret); |
@@ -217,7 +215,6 @@ MODULE_DEVICE_TABLE(of, innolux_of_match); | |||
217 | static int innolux_panel_add(struct innolux_panel *innolux) | 215 | static int innolux_panel_add(struct innolux_panel *innolux) |
218 | { | 216 | { |
219 | struct device *dev = &innolux->link->dev; | 217 | struct device *dev = &innolux->link->dev; |
220 | struct device_node *np; | ||
221 | int err; | 218 | int err; |
222 | 219 | ||
223 | innolux->supply = devm_regulator_get(dev, "power"); | 220 | innolux->supply = devm_regulator_get(dev, "power"); |
@@ -232,37 +229,22 @@ static int innolux_panel_add(struct innolux_panel *innolux) | |||
232 | innolux->enable_gpio = NULL; | 229 | innolux->enable_gpio = NULL; |
233 | } | 230 | } |
234 | 231 | ||
235 | np = of_parse_phandle(dev->of_node, "backlight", 0); | 232 | innolux->backlight = devm_of_find_backlight(dev); |
236 | if (np) { | ||
237 | innolux->backlight = of_find_backlight_by_node(np); | ||
238 | of_node_put(np); | ||
239 | 233 | ||
240 | if (!innolux->backlight) | 234 | if (IS_ERR(innolux->backlight)) |
241 | return -EPROBE_DEFER; | 235 | return PTR_ERR(innolux->backlight); |
242 | } | ||
243 | 236 | ||
244 | drm_panel_init(&innolux->base); | 237 | drm_panel_init(&innolux->base); |
245 | innolux->base.funcs = &innolux_panel_funcs; | 238 | innolux->base.funcs = &innolux_panel_funcs; |
246 | innolux->base.dev = &innolux->link->dev; | 239 | innolux->base.dev = &innolux->link->dev; |
247 | 240 | ||
248 | err = drm_panel_add(&innolux->base); | 241 | return drm_panel_add(&innolux->base); |
249 | if (err < 0) | ||
250 | goto put_backlight; | ||
251 | |||
252 | return 0; | ||
253 | |||
254 | put_backlight: | ||
255 | put_device(&innolux->backlight->dev); | ||
256 | |||
257 | return err; | ||
258 | } | 242 | } |
259 | 243 | ||
260 | static void innolux_panel_del(struct innolux_panel *innolux) | 244 | static void innolux_panel_del(struct innolux_panel *innolux) |
261 | { | 245 | { |
262 | if (innolux->base.dev) | 246 | if (innolux->base.dev) |
263 | drm_panel_remove(&innolux->base); | 247 | drm_panel_remove(&innolux->base); |
264 | |||
265 | put_device(&innolux->backlight->dev); | ||
266 | } | 248 | } |
267 | 249 | ||
268 | static int innolux_panel_probe(struct mipi_dsi_device *dsi) | 250 | static int innolux_panel_probe(struct mipi_dsi_device *dsi) |
diff --git a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c index 5b2340ef74ed..0a94ab79a6c0 100644 --- a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c +++ b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c | |||
@@ -192,8 +192,7 @@ static int jdi_panel_disable(struct drm_panel *panel) | |||
192 | if (!jdi->enabled) | 192 | if (!jdi->enabled) |
193 | return 0; | 193 | return 0; |
194 | 194 | ||
195 | jdi->backlight->props.power = FB_BLANK_POWERDOWN; | 195 | backlight_disable(jdi->backlight); |
196 | backlight_update_status(jdi->backlight); | ||
197 | 196 | ||
198 | jdi->enabled = false; | 197 | jdi->enabled = false; |
199 | 198 | ||
@@ -289,8 +288,7 @@ static int jdi_panel_enable(struct drm_panel *panel) | |||
289 | if (jdi->enabled) | 288 | if (jdi->enabled) |
290 | return 0; | 289 | return 0; |
291 | 290 | ||
292 | jdi->backlight->props.power = FB_BLANK_UNBLANK; | 291 | backlight_enable(jdi->backlight); |
293 | backlight_update_status(jdi->backlight); | ||
294 | 292 | ||
295 | jdi->enabled = true; | 293 | jdi->enabled = true; |
296 | 294 | ||
diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c index 3cce3ca19601..6bf8730f1a21 100644 --- a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c +++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c | |||
@@ -96,10 +96,7 @@ static int sharp_panel_disable(struct drm_panel *panel) | |||
96 | if (!sharp->enabled) | 96 | if (!sharp->enabled) |
97 | return 0; | 97 | return 0; |
98 | 98 | ||
99 | if (sharp->backlight) { | 99 | backlight_disable(sharp->backlight); |
100 | sharp->backlight->props.power = FB_BLANK_POWERDOWN; | ||
101 | backlight_update_status(sharp->backlight); | ||
102 | } | ||
103 | 100 | ||
104 | sharp->enabled = false; | 101 | sharp->enabled = false; |
105 | 102 | ||
@@ -263,10 +260,7 @@ static int sharp_panel_enable(struct drm_panel *panel) | |||
263 | if (sharp->enabled) | 260 | if (sharp->enabled) |
264 | return 0; | 261 | return 0; |
265 | 262 | ||
266 | if (sharp->backlight) { | 263 | backlight_enable(sharp->backlight); |
267 | sharp->backlight->props.power = FB_BLANK_UNBLANK; | ||
268 | backlight_update_status(sharp->backlight); | ||
269 | } | ||
270 | 264 | ||
271 | sharp->enabled = true; | 265 | sharp->enabled = true; |
272 | 266 | ||
@@ -324,8 +318,7 @@ MODULE_DEVICE_TABLE(of, sharp_of_match); | |||
324 | 318 | ||
325 | static int sharp_panel_add(struct sharp_panel *sharp) | 319 | static int sharp_panel_add(struct sharp_panel *sharp) |
326 | { | 320 | { |
327 | struct device_node *np; | 321 | struct device *dev = &sharp->link1->dev; |
328 | int err; | ||
329 | 322 | ||
330 | sharp->mode = &default_mode; | 323 | sharp->mode = &default_mode; |
331 | 324 | ||
@@ -333,30 +326,16 @@ static int sharp_panel_add(struct sharp_panel *sharp) | |||
333 | if (IS_ERR(sharp->supply)) | 326 | if (IS_ERR(sharp->supply)) |
334 | return PTR_ERR(sharp->supply); | 327 | return PTR_ERR(sharp->supply); |
335 | 328 | ||
336 | np = of_parse_phandle(sharp->link1->dev.of_node, "backlight", 0); | 329 | sharp->backlight = devm_of_find_backlight(dev); |
337 | if (np) { | ||
338 | sharp->backlight = of_find_backlight_by_node(np); | ||
339 | of_node_put(np); | ||
340 | 330 | ||
341 | if (!sharp->backlight) | 331 | if (IS_ERR(sharp->backlight)) |
342 | return -EPROBE_DEFER; | 332 | return PTR_ERR(sharp->backlight); |
343 | } | ||
344 | 333 | ||
345 | drm_panel_init(&sharp->base); | 334 | drm_panel_init(&sharp->base); |
346 | sharp->base.funcs = &sharp_panel_funcs; | 335 | sharp->base.funcs = &sharp_panel_funcs; |
347 | sharp->base.dev = &sharp->link1->dev; | 336 | sharp->base.dev = &sharp->link1->dev; |
348 | 337 | ||
349 | err = drm_panel_add(&sharp->base); | 338 | return drm_panel_add(&sharp->base); |
350 | if (err < 0) | ||
351 | goto put_backlight; | ||
352 | |||
353 | return 0; | ||
354 | |||
355 | put_backlight: | ||
356 | if (sharp->backlight) | ||
357 | put_device(&sharp->backlight->dev); | ||
358 | |||
359 | return err; | ||
360 | } | 339 | } |
361 | 340 | ||
362 | static void sharp_panel_del(struct sharp_panel *sharp) | 341 | static void sharp_panel_del(struct sharp_panel *sharp) |
@@ -364,9 +343,6 @@ static void sharp_panel_del(struct sharp_panel *sharp) | |||
364 | if (sharp->base.dev) | 343 | if (sharp->base.dev) |
365 | drm_panel_remove(&sharp->base); | 344 | drm_panel_remove(&sharp->base); |
366 | 345 | ||
367 | if (sharp->backlight) | ||
368 | put_device(&sharp->backlight->dev); | ||
369 | |||
370 | if (sharp->link2) | 346 | if (sharp->link2) |
371 | put_device(&sharp->link2->dev); | 347 | put_device(&sharp->link2->dev); |
372 | } | 348 | } |
diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c index 3aeb0bda4947..494aa9b1628a 100644 --- a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c +++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c | |||
@@ -117,10 +117,7 @@ static int sharp_nt_panel_disable(struct drm_panel *panel) | |||
117 | if (!sharp_nt->enabled) | 117 | if (!sharp_nt->enabled) |
118 | return 0; | 118 | return 0; |
119 | 119 | ||
120 | if (sharp_nt->backlight) { | 120 | backlight_disable(sharp_nt->backlight); |
121 | sharp_nt->backlight->props.power = FB_BLANK_POWERDOWN; | ||
122 | backlight_update_status(sharp_nt->backlight); | ||
123 | } | ||
124 | 121 | ||
125 | sharp_nt->enabled = false; | 122 | sharp_nt->enabled = false; |
126 | 123 | ||
@@ -203,10 +200,7 @@ static int sharp_nt_panel_enable(struct drm_panel *panel) | |||
203 | if (sharp_nt->enabled) | 200 | if (sharp_nt->enabled) |
204 | return 0; | 201 | return 0; |
205 | 202 | ||
206 | if (sharp_nt->backlight) { | 203 | backlight_enable(sharp_nt->backlight); |
207 | sharp_nt->backlight->props.power = FB_BLANK_UNBLANK; | ||
208 | backlight_update_status(sharp_nt->backlight); | ||
209 | } | ||
210 | 204 | ||
211 | sharp_nt->enabled = true; | 205 | sharp_nt->enabled = true; |
212 | 206 | ||
@@ -259,8 +253,6 @@ static const struct drm_panel_funcs sharp_nt_panel_funcs = { | |||
259 | static int sharp_nt_panel_add(struct sharp_nt_panel *sharp_nt) | 253 | static int sharp_nt_panel_add(struct sharp_nt_panel *sharp_nt) |
260 | { | 254 | { |
261 | struct device *dev = &sharp_nt->dsi->dev; | 255 | struct device *dev = &sharp_nt->dsi->dev; |
262 | struct device_node *np; | ||
263 | int ret; | ||
264 | 256 | ||
265 | sharp_nt->mode = &default_mode; | 257 | sharp_nt->mode = &default_mode; |
266 | 258 | ||
@@ -277,39 +269,22 @@ static int sharp_nt_panel_add(struct sharp_nt_panel *sharp_nt) | |||
277 | gpiod_set_value(sharp_nt->reset_gpio, 0); | 269 | gpiod_set_value(sharp_nt->reset_gpio, 0); |
278 | } | 270 | } |
279 | 271 | ||
280 | np = of_parse_phandle(dev->of_node, "backlight", 0); | 272 | sharp_nt->backlight = devm_of_find_backlight(dev); |
281 | if (np) { | ||
282 | sharp_nt->backlight = of_find_backlight_by_node(np); | ||
283 | of_node_put(np); | ||
284 | 273 | ||
285 | if (!sharp_nt->backlight) | 274 | if (IS_ERR(sharp_nt->backlight)) |
286 | return -EPROBE_DEFER; | 275 | return PTR_ERR(sharp_nt->backlight); |
287 | } | ||
288 | 276 | ||
289 | drm_panel_init(&sharp_nt->base); | 277 | drm_panel_init(&sharp_nt->base); |
290 | sharp_nt->base.funcs = &sharp_nt_panel_funcs; | 278 | sharp_nt->base.funcs = &sharp_nt_panel_funcs; |
291 | sharp_nt->base.dev = &sharp_nt->dsi->dev; | 279 | sharp_nt->base.dev = &sharp_nt->dsi->dev; |
292 | 280 | ||
293 | ret = drm_panel_add(&sharp_nt->base); | 281 | return 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 | } | 282 | } |
305 | 283 | ||
306 | static void sharp_nt_panel_del(struct sharp_nt_panel *sharp_nt) | 284 | static void sharp_nt_panel_del(struct sharp_nt_panel *sharp_nt) |
307 | { | 285 | { |
308 | if (sharp_nt->base.dev) | 286 | if (sharp_nt->base.dev) |
309 | drm_panel_remove(&sharp_nt->base); | 287 | drm_panel_remove(&sharp_nt->base); |
310 | |||
311 | if (sharp_nt->backlight) | ||
312 | put_device(&sharp_nt->backlight->dev); | ||
313 | } | 288 | } |
314 | 289 | ||
315 | static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi) | 290 | static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi) |
diff --git a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c index dc85b53d58ef..76210ae25094 100644 --- a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c +++ b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | |||
@@ -68,12 +68,22 @@ static const struct dw_hdmi_plat_data rcar_dw_hdmi_plat_data = { | |||
68 | 68 | ||
69 | static int rcar_dw_hdmi_probe(struct platform_device *pdev) | 69 | static int rcar_dw_hdmi_probe(struct platform_device *pdev) |
70 | { | 70 | { |
71 | return dw_hdmi_probe(pdev, &rcar_dw_hdmi_plat_data); | 71 | struct dw_hdmi *hdmi; |
72 | |||
73 | hdmi = dw_hdmi_probe(pdev, &rcar_dw_hdmi_plat_data); | ||
74 | if (IS_ERR(hdmi)) | ||
75 | return PTR_ERR(hdmi); | ||
76 | |||
77 | platform_set_drvdata(pdev, hdmi); | ||
78 | |||
79 | return 0; | ||
72 | } | 80 | } |
73 | 81 | ||
74 | static int rcar_dw_hdmi_remove(struct platform_device *pdev) | 82 | static int rcar_dw_hdmi_remove(struct platform_device *pdev) |
75 | { | 83 | { |
76 | dw_hdmi_remove(pdev); | 84 | struct dw_hdmi *hdmi = platform_get_drvdata(pdev); |
85 | |||
86 | dw_hdmi_remove(hdmi); | ||
77 | 87 | ||
78 | return 0; | 88 | return 0; |
79 | } | 89 | } |
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index b1fe0639227e..591953cbdd18 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c | |||
@@ -1202,9 +1202,6 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master, | |||
1202 | return ret; | 1202 | return ret; |
1203 | 1203 | ||
1204 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1204 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1205 | if (!res) | ||
1206 | return -ENODEV; | ||
1207 | |||
1208 | dsi->base = devm_ioremap_resource(dev, res); | 1205 | dsi->base = devm_ioremap_resource(dev, res); |
1209 | if (IS_ERR(dsi->base)) | 1206 | if (IS_ERR(dsi->base)) |
1210 | return PTR_ERR(dsi->base); | 1207 | return PTR_ERR(dsi->base); |
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 1eb02a82fd91..3574b0ae2ad1 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | |||
@@ -48,6 +48,7 @@ struct rockchip_hdmi { | |||
48 | const struct rockchip_hdmi_chip_data *chip_data; | 48 | const struct rockchip_hdmi_chip_data *chip_data; |
49 | struct clk *vpll_clk; | 49 | struct clk *vpll_clk; |
50 | struct clk *grf_clk; | 50 | struct clk *grf_clk; |
51 | struct dw_hdmi *hdmi; | ||
51 | }; | 52 | }; |
52 | 53 | ||
53 | #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) | 54 | #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) |
@@ -377,14 +378,18 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, | |||
377 | drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs, | 378 | drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs, |
378 | DRM_MODE_ENCODER_TMDS, NULL); | 379 | DRM_MODE_ENCODER_TMDS, NULL); |
379 | 380 | ||
380 | ret = dw_hdmi_bind(pdev, encoder, plat_data); | 381 | platform_set_drvdata(pdev, hdmi); |
382 | |||
383 | hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); | ||
381 | 384 | ||
382 | /* | 385 | /* |
383 | * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), | 386 | * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), |
384 | * which would have called the encoder cleanup. Do it manually. | 387 | * which would have called the encoder cleanup. Do it manually. |
385 | */ | 388 | */ |
386 | if (ret) | 389 | if (IS_ERR(hdmi->hdmi)) { |
390 | ret = PTR_ERR(hdmi->hdmi); | ||
387 | drm_encoder_cleanup(encoder); | 391 | drm_encoder_cleanup(encoder); |
392 | } | ||
388 | 393 | ||
389 | return ret; | 394 | return ret; |
390 | } | 395 | } |
@@ -392,7 +397,9 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, | |||
392 | static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, | 397 | static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, |
393 | void *data) | 398 | void *data) |
394 | { | 399 | { |
395 | return dw_hdmi_unbind(dev); | 400 | struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); |
401 | |||
402 | dw_hdmi_unbind(hdmi->hdmi); | ||
396 | } | 403 | } |
397 | 404 | ||
398 | static const struct component_ops dw_hdmi_rockchip_ops = { | 405 | static const struct component_ops dw_hdmi_rockchip_ops = { |
diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index fab30927a889..f6ad48766d49 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c | |||
@@ -831,9 +831,6 @@ static int inno_hdmi_bind(struct device *dev, struct device *master, | |||
831 | hdmi->drm_dev = drm; | 831 | hdmi->drm_dev = drm; |
832 | 832 | ||
833 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 833 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
834 | if (!iores) | ||
835 | return -ENXIO; | ||
836 | |||
837 | hdmi->regs = devm_ioremap_resource(dev, iores); | 834 | hdmi->regs = devm_ioremap_resource(dev, iores); |
838 | if (IS_ERR(hdmi->regs)) | 835 | if (IS_ERR(hdmi->regs)) |
839 | return PTR_ERR(hdmi->regs); | 836 | return PTR_ERR(hdmi->regs); |
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index d85431400a0d..88084ca15115 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c | |||
@@ -230,6 +230,7 @@ static struct drm_driver rockchip_drm_driver = { | |||
230 | .gem_prime_import = drm_gem_prime_import, | 230 | .gem_prime_import = drm_gem_prime_import, |
231 | .gem_prime_export = drm_gem_prime_export, | 231 | .gem_prime_export = drm_gem_prime_export, |
232 | .gem_prime_get_sg_table = rockchip_gem_prime_get_sg_table, | 232 | .gem_prime_get_sg_table = rockchip_gem_prime_get_sg_table, |
233 | .gem_prime_import_sg_table = rockchip_gem_prime_import_sg_table, | ||
233 | .gem_prime_vmap = rockchip_gem_prime_vmap, | 234 | .gem_prime_vmap = rockchip_gem_prime_vmap, |
234 | .gem_prime_vunmap = rockchip_gem_prime_vunmap, | 235 | .gem_prime_vunmap = rockchip_gem_prime_vunmap, |
235 | .gem_prime_mmap = rockchip_gem_mmap_buf, | 236 | .gem_prime_mmap = rockchip_gem_mmap_buf, |
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index 1d9655576b6e..074db7a92809 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <drm/drmP.h> | 16 | #include <drm/drmP.h> |
17 | #include <drm/drm_gem.h> | 17 | #include <drm/drm_gem.h> |
18 | #include <drm/drm_vma_manager.h> | 18 | #include <drm/drm_vma_manager.h> |
19 | |||
20 | #include <linux/dma-buf.h> | ||
19 | #include <linux/iommu.h> | 21 | #include <linux/iommu.h> |
20 | 22 | ||
21 | #include "rockchip_drm_drv.h" | 23 | #include "rockchip_drm_drv.h" |
@@ -262,7 +264,6 @@ static int rockchip_drm_gem_object_mmap(struct drm_gem_object *obj, | |||
262 | * VM_PFNMAP flag that was set by drm_gem_mmap_obj()/drm_gem_mmap(). | 264 | * VM_PFNMAP flag that was set by drm_gem_mmap_obj()/drm_gem_mmap(). |
263 | */ | 265 | */ |
264 | vma->vm_flags &= ~VM_PFNMAP; | 266 | vma->vm_flags &= ~VM_PFNMAP; |
265 | vma->vm_pgoff = 0; | ||
266 | 267 | ||
267 | if (rk_obj->pages) | 268 | if (rk_obj->pages) |
268 | ret = rockchip_drm_gem_object_mmap_iommu(obj, vma); | 269 | ret = rockchip_drm_gem_object_mmap_iommu(obj, vma); |
@@ -297,6 +298,12 @@ int rockchip_gem_mmap(struct file *filp, struct vm_area_struct *vma) | |||
297 | if (ret) | 298 | if (ret) |
298 | return ret; | 299 | return ret; |
299 | 300 | ||
301 | /* | ||
302 | * Set vm_pgoff (used as a fake buffer offset by DRM) to 0 and map the | ||
303 | * whole buffer from the start. | ||
304 | */ | ||
305 | vma->vm_pgoff = 0; | ||
306 | |||
300 | obj = vma->vm_private_data; | 307 | obj = vma->vm_private_data; |
301 | 308 | ||
302 | return rockchip_drm_gem_object_mmap(obj, vma); | 309 | return rockchip_drm_gem_object_mmap(obj, vma); |
@@ -309,12 +316,10 @@ static void rockchip_gem_release_object(struct rockchip_gem_object *rk_obj) | |||
309 | } | 316 | } |
310 | 317 | ||
311 | struct rockchip_gem_object * | 318 | struct rockchip_gem_object * |
312 | rockchip_gem_create_object(struct drm_device *drm, unsigned int size, | 319 | rockchip_gem_alloc_object(struct drm_device *drm, unsigned int size) |
313 | bool alloc_kmap) | ||
314 | { | 320 | { |
315 | struct rockchip_gem_object *rk_obj; | 321 | struct rockchip_gem_object *rk_obj; |
316 | struct drm_gem_object *obj; | 322 | struct drm_gem_object *obj; |
317 | int ret; | ||
318 | 323 | ||
319 | size = round_up(size, PAGE_SIZE); | 324 | size = round_up(size, PAGE_SIZE); |
320 | 325 | ||
@@ -326,6 +331,20 @@ struct rockchip_gem_object * | |||
326 | 331 | ||
327 | drm_gem_object_init(drm, obj, size); | 332 | drm_gem_object_init(drm, obj, size); |
328 | 333 | ||
334 | return rk_obj; | ||
335 | } | ||
336 | |||
337 | struct rockchip_gem_object * | ||
338 | rockchip_gem_create_object(struct drm_device *drm, unsigned int size, | ||
339 | bool alloc_kmap) | ||
340 | { | ||
341 | struct rockchip_gem_object *rk_obj; | ||
342 | int ret; | ||
343 | |||
344 | rk_obj = rockchip_gem_alloc_object(drm, size); | ||
345 | if (IS_ERR(rk_obj)) | ||
346 | return rk_obj; | ||
347 | |||
329 | ret = rockchip_gem_alloc_buf(rk_obj, alloc_kmap); | 348 | ret = rockchip_gem_alloc_buf(rk_obj, alloc_kmap); |
330 | if (ret) | 349 | if (ret) |
331 | goto err_free_rk_obj; | 350 | goto err_free_rk_obj; |
@@ -343,11 +362,21 @@ err_free_rk_obj: | |||
343 | */ | 362 | */ |
344 | void rockchip_gem_free_object(struct drm_gem_object *obj) | 363 | void rockchip_gem_free_object(struct drm_gem_object *obj) |
345 | { | 364 | { |
346 | struct rockchip_gem_object *rk_obj; | 365 | struct drm_device *drm = obj->dev; |
347 | 366 | struct rockchip_drm_private *private = drm->dev_private; | |
348 | rk_obj = to_rockchip_obj(obj); | 367 | struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); |
349 | 368 | ||
350 | rockchip_gem_free_buf(rk_obj); | 369 | if (obj->import_attach) { |
370 | if (private->domain) { | ||
371 | rockchip_gem_iommu_unmap(rk_obj); | ||
372 | } else { | ||
373 | dma_unmap_sg(drm->dev, rk_obj->sgt->sgl, | ||
374 | rk_obj->sgt->nents, DMA_BIDIRECTIONAL); | ||
375 | } | ||
376 | drm_prime_gem_destroy(obj, rk_obj->sgt); | ||
377 | } else { | ||
378 | rockchip_gem_free_buf(rk_obj); | ||
379 | } | ||
351 | 380 | ||
352 | rockchip_gem_release_object(rk_obj); | 381 | rockchip_gem_release_object(rk_obj); |
353 | } | 382 | } |
@@ -451,6 +480,86 @@ struct sg_table *rockchip_gem_prime_get_sg_table(struct drm_gem_object *obj) | |||
451 | return sgt; | 480 | return sgt; |
452 | } | 481 | } |
453 | 482 | ||
483 | static unsigned long rockchip_sg_get_contiguous_size(struct sg_table *sgt, | ||
484 | int count) | ||
485 | { | ||
486 | struct scatterlist *s; | ||
487 | dma_addr_t expected = sg_dma_address(sgt->sgl); | ||
488 | unsigned int i; | ||
489 | unsigned long size = 0; | ||
490 | |||
491 | for_each_sg(sgt->sgl, s, count, i) { | ||
492 | if (sg_dma_address(s) != expected) | ||
493 | break; | ||
494 | expected = sg_dma_address(s) + sg_dma_len(s); | ||
495 | size += sg_dma_len(s); | ||
496 | } | ||
497 | return size; | ||
498 | } | ||
499 | |||
500 | static int | ||
501 | rockchip_gem_iommu_map_sg(struct drm_device *drm, | ||
502 | struct dma_buf_attachment *attach, | ||
503 | struct sg_table *sg, | ||
504 | struct rockchip_gem_object *rk_obj) | ||
505 | { | ||
506 | rk_obj->sgt = sg; | ||
507 | return rockchip_gem_iommu_map(rk_obj); | ||
508 | } | ||
509 | |||
510 | static int | ||
511 | rockchip_gem_dma_map_sg(struct drm_device *drm, | ||
512 | struct dma_buf_attachment *attach, | ||
513 | struct sg_table *sg, | ||
514 | struct rockchip_gem_object *rk_obj) | ||
515 | { | ||
516 | int count = dma_map_sg(drm->dev, sg->sgl, sg->nents, | ||
517 | DMA_BIDIRECTIONAL); | ||
518 | if (!count) | ||
519 | return -EINVAL; | ||
520 | |||
521 | if (rockchip_sg_get_contiguous_size(sg, count) < attach->dmabuf->size) { | ||
522 | DRM_ERROR("failed to map sg_table to contiguous linear address.\n"); | ||
523 | dma_unmap_sg(drm->dev, sg->sgl, sg->nents, | ||
524 | DMA_BIDIRECTIONAL); | ||
525 | return -EINVAL; | ||
526 | } | ||
527 | |||
528 | rk_obj->dma_addr = sg_dma_address(sg->sgl); | ||
529 | rk_obj->sgt = sg; | ||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | struct drm_gem_object * | ||
534 | rockchip_gem_prime_import_sg_table(struct drm_device *drm, | ||
535 | struct dma_buf_attachment *attach, | ||
536 | struct sg_table *sg) | ||
537 | { | ||
538 | struct rockchip_drm_private *private = drm->dev_private; | ||
539 | struct rockchip_gem_object *rk_obj; | ||
540 | int ret; | ||
541 | |||
542 | rk_obj = rockchip_gem_alloc_object(drm, attach->dmabuf->size); | ||
543 | if (IS_ERR(rk_obj)) | ||
544 | return ERR_CAST(rk_obj); | ||
545 | |||
546 | if (private->domain) | ||
547 | ret = rockchip_gem_iommu_map_sg(drm, attach, sg, rk_obj); | ||
548 | else | ||
549 | ret = rockchip_gem_dma_map_sg(drm, attach, sg, rk_obj); | ||
550 | |||
551 | if (ret < 0) { | ||
552 | DRM_ERROR("failed to import sg table: %d\n", ret); | ||
553 | goto err_free_rk_obj; | ||
554 | } | ||
555 | |||
556 | return &rk_obj->base; | ||
557 | |||
558 | err_free_rk_obj: | ||
559 | rockchip_gem_release_object(rk_obj); | ||
560 | return ERR_PTR(ret); | ||
561 | } | ||
562 | |||
454 | void *rockchip_gem_prime_vmap(struct drm_gem_object *obj) | 563 | void *rockchip_gem_prime_vmap(struct drm_gem_object *obj) |
455 | { | 564 | { |
456 | struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); | 565 | struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); |
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h index f237375582fb..d41fa65219d2 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h | |||
@@ -36,8 +36,9 @@ struct rockchip_gem_object { | |||
36 | 36 | ||
37 | struct sg_table *rockchip_gem_prime_get_sg_table(struct drm_gem_object *obj); | 37 | struct sg_table *rockchip_gem_prime_get_sg_table(struct drm_gem_object *obj); |
38 | struct drm_gem_object * | 38 | struct drm_gem_object * |
39 | rockchip_gem_prime_import_sg_table(struct drm_device *dev, size_t size, | 39 | rockchip_gem_prime_import_sg_table(struct drm_device *dev, |
40 | struct sg_table *sgt); | 40 | struct dma_buf_attachment *attach, |
41 | struct sg_table *sg); | ||
41 | void *rockchip_gem_prime_vmap(struct drm_gem_object *obj); | 42 | void *rockchip_gem_prime_vmap(struct drm_gem_object *obj); |
42 | void rockchip_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); | 43 | void rockchip_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); |
43 | 44 | ||
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 7715853ef90a..66736227c96e 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c | |||
@@ -95,9 +95,6 @@ struct vop { | |||
95 | struct drm_device *drm_dev; | 95 | struct drm_device *drm_dev; |
96 | bool is_enabled; | 96 | bool is_enabled; |
97 | 97 | ||
98 | /* mutex vsync_ work */ | ||
99 | struct mutex vsync_mutex; | ||
100 | bool vsync_work_pending; | ||
101 | struct completion dsp_hold_completion; | 98 | struct completion dsp_hold_completion; |
102 | 99 | ||
103 | /* protected by dev->event_lock */ | 100 | /* protected by dev->event_lock */ |
@@ -1555,8 +1552,6 @@ static int vop_bind(struct device *dev, struct device *master, void *data) | |||
1555 | spin_lock_init(&vop->reg_lock); | 1552 | spin_lock_init(&vop->reg_lock); |
1556 | spin_lock_init(&vop->irq_lock); | 1553 | spin_lock_init(&vop->irq_lock); |
1557 | 1554 | ||
1558 | mutex_init(&vop->vsync_mutex); | ||
1559 | |||
1560 | ret = devm_request_irq(dev, vop->irq, vop_isr, | 1555 | ret = devm_request_irq(dev, vop->irq, vop_isr, |
1561 | IRQF_SHARED, dev_name(dev), vop); | 1556 | IRQF_SHARED, dev_name(dev), vop); |
1562 | if (ret) | 1557 | if (ret) |
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig index 882d85db9053..7327da3bc94f 100644 --- a/drivers/gpu/drm/sun4i/Kconfig +++ b/drivers/gpu/drm/sun4i/Kconfig | |||
@@ -40,6 +40,15 @@ config DRM_SUN4I_BACKEND | |||
40 | do some alpha blending and feed graphics to TCON. If M is | 40 | do some alpha blending and feed graphics to TCON. If M is |
41 | selected the module will be called sun4i-backend. | 41 | selected the module will be called sun4i-backend. |
42 | 42 | ||
43 | config DRM_SUN8I_DW_HDMI | ||
44 | tristate "Support for Allwinner version of DesignWare HDMI" | ||
45 | depends on DRM_SUN4I | ||
46 | select DRM_DW_HDMI | ||
47 | help | ||
48 | Choose this option if you have an Allwinner SoC with the | ||
49 | DesignWare HDMI controller with custom HDMI PHY. If M is | ||
50 | selected the module will be called sun8i_dw_hdmi. | ||
51 | |||
43 | config DRM_SUN8I_MIXER | 52 | config DRM_SUN8I_MIXER |
44 | tristate "Support for Allwinner Display Engine 2.0 Mixer" | 53 | tristate "Support for Allwinner Display Engine 2.0 Mixer" |
45 | default MACH_SUN8I | 54 | default MACH_SUN8I |
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile index 582607c0c488..1610e748119b 100644 --- a/drivers/gpu/drm/sun4i/Makefile +++ b/drivers/gpu/drm/sun4i/Makefile | |||
@@ -10,6 +10,9 @@ sun4i-drm-hdmi-y += sun4i_hdmi_enc.o | |||
10 | sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o | 10 | sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o |
11 | sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o | 11 | sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o |
12 | 12 | ||
13 | sun8i-drm-hdmi-y += sun8i_dw_hdmi.o | ||
14 | sun8i-drm-hdmi-y += sun8i_hdmi_phy.o | ||
15 | |||
13 | sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \ | 16 | sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \ |
14 | sun8i_vi_layer.o sun8i_ui_scaler.o \ | 17 | sun8i_vi_layer.o sun8i_ui_scaler.o \ |
15 | sun8i_vi_scaler.o sun8i_csc.o | 18 | sun8i_vi_scaler.o sun8i_csc.o |
@@ -27,4 +30,5 @@ obj-$(CONFIG_DRM_SUN4I) += sun6i_drc.o | |||
27 | 30 | ||
28 | obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o sun4i-frontend.o | 31 | obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o sun4i-frontend.o |
29 | obj-$(CONFIG_DRM_SUN4I_HDMI) += sun4i-drm-hdmi.o | 32 | obj-$(CONFIG_DRM_SUN4I_HDMI) += sun4i-drm-hdmi.o |
33 | obj-$(CONFIG_DRM_SUN8I_DW_HDMI) += sun8i-drm-hdmi.o | ||
30 | obj-$(CONFIG_DRM_SUN8I_MIXER) += sun8i-mixer.o | 34 | obj-$(CONFIG_DRM_SUN8I_MIXER) += sun8i-mixer.o |
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 4b7340ee6290..0d6c5ed44795 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c | |||
@@ -84,6 +84,7 @@ static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel, | |||
84 | 84 | ||
85 | switch (channel) { | 85 | switch (channel) { |
86 | case 0: | 86 | case 0: |
87 | WARN_ON(!tcon->quirks->has_channel_0); | ||
87 | regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, | 88 | regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, |
88 | SUN4I_TCON0_CTL_TCON_ENABLE, | 89 | SUN4I_TCON0_CTL_TCON_ENABLE, |
89 | enabled ? SUN4I_TCON0_CTL_TCON_ENABLE : 0); | 90 | enabled ? SUN4I_TCON0_CTL_TCON_ENABLE : 0); |
@@ -276,6 +277,8 @@ static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon, | |||
276 | u8 clk_delay; | 277 | u8 clk_delay; |
277 | u32 reg, val = 0; | 278 | u32 reg, val = 0; |
278 | 279 | ||
280 | WARN_ON(!tcon->quirks->has_channel_0); | ||
281 | |||
279 | tcon->dclk_min_div = 7; | 282 | tcon->dclk_min_div = 7; |
280 | tcon->dclk_max_div = 7; | 283 | tcon->dclk_max_div = 7; |
281 | sun4i_tcon0_mode_set_common(tcon, mode); | 284 | sun4i_tcon0_mode_set_common(tcon, mode); |
@@ -344,6 +347,8 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, | |||
344 | u8 clk_delay; | 347 | u8 clk_delay; |
345 | u32 val = 0; | 348 | u32 val = 0; |
346 | 349 | ||
350 | WARN_ON(!tcon->quirks->has_channel_0); | ||
351 | |||
347 | tcon->dclk_min_div = 6; | 352 | tcon->dclk_min_div = 6; |
348 | tcon->dclk_max_div = 127; | 353 | tcon->dclk_max_div = 127; |
349 | sun4i_tcon0_mode_set_common(tcon, mode); | 354 | sun4i_tcon0_mode_set_common(tcon, mode); |
@@ -389,10 +394,10 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, | |||
389 | SUN4I_TCON0_BASIC3_H_SYNC(hsync)); | 394 | SUN4I_TCON0_BASIC3_H_SYNC(hsync)); |
390 | 395 | ||
391 | /* Setup the polarity of the various signals */ | 396 | /* Setup the polarity of the various signals */ |
392 | if (!(mode->flags & DRM_MODE_FLAG_PHSYNC)) | 397 | if (mode->flags & DRM_MODE_FLAG_PHSYNC) |
393 | val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE; | 398 | val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE; |
394 | 399 | ||
395 | if (!(mode->flags & DRM_MODE_FLAG_PVSYNC)) | 400 | if (mode->flags & DRM_MODE_FLAG_PVSYNC) |
396 | val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE; | 401 | val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE; |
397 | 402 | ||
398 | regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG, | 403 | regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG, |
@@ -574,10 +579,12 @@ static int sun4i_tcon_init_clocks(struct device *dev, | |||
574 | } | 579 | } |
575 | clk_prepare_enable(tcon->clk); | 580 | clk_prepare_enable(tcon->clk); |
576 | 581 | ||
577 | tcon->sclk0 = devm_clk_get(dev, "tcon-ch0"); | 582 | if (tcon->quirks->has_channel_0) { |
578 | if (IS_ERR(tcon->sclk0)) { | 583 | tcon->sclk0 = devm_clk_get(dev, "tcon-ch0"); |
579 | dev_err(dev, "Couldn't get the TCON channel 0 clock\n"); | 584 | if (IS_ERR(tcon->sclk0)) { |
580 | return PTR_ERR(tcon->sclk0); | 585 | dev_err(dev, "Couldn't get the TCON channel 0 clock\n"); |
586 | return PTR_ERR(tcon->sclk0); | ||
587 | } | ||
581 | } | 588 | } |
582 | 589 | ||
583 | if (tcon->quirks->has_channel_1) { | 590 | if (tcon->quirks->has_channel_1) { |
@@ -934,10 +941,12 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, | |||
934 | goto err_free_clocks; | 941 | goto err_free_clocks; |
935 | } | 942 | } |
936 | 943 | ||
937 | ret = sun4i_dclk_create(dev, tcon); | 944 | if (tcon->quirks->has_channel_0) { |
938 | if (ret) { | 945 | ret = sun4i_dclk_create(dev, tcon); |
939 | dev_err(dev, "Couldn't create our TCON dot clock\n"); | 946 | if (ret) { |
940 | goto err_free_clocks; | 947 | dev_err(dev, "Couldn't create our TCON dot clock\n"); |
948 | goto err_free_clocks; | ||
949 | } | ||
941 | } | 950 | } |
942 | 951 | ||
943 | ret = sun4i_tcon_init_irq(dev, tcon); | 952 | ret = sun4i_tcon_init_irq(dev, tcon); |
@@ -995,7 +1004,8 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, | |||
995 | return 0; | 1004 | return 0; |
996 | 1005 | ||
997 | err_free_dotclock: | 1006 | err_free_dotclock: |
998 | sun4i_dclk_free(tcon); | 1007 | if (tcon->quirks->has_channel_0) |
1008 | sun4i_dclk_free(tcon); | ||
999 | err_free_clocks: | 1009 | err_free_clocks: |
1000 | sun4i_tcon_free_clocks(tcon); | 1010 | sun4i_tcon_free_clocks(tcon); |
1001 | err_assert_reset: | 1011 | err_assert_reset: |
@@ -1009,7 +1019,8 @@ static void sun4i_tcon_unbind(struct device *dev, struct device *master, | |||
1009 | struct sun4i_tcon *tcon = dev_get_drvdata(dev); | 1019 | struct sun4i_tcon *tcon = dev_get_drvdata(dev); |
1010 | 1020 | ||
1011 | list_del(&tcon->list); | 1021 | list_del(&tcon->list); |
1012 | sun4i_dclk_free(tcon); | 1022 | if (tcon->quirks->has_channel_0) |
1023 | sun4i_dclk_free(tcon); | ||
1013 | sun4i_tcon_free_clocks(tcon); | 1024 | sun4i_tcon_free_clocks(tcon); |
1014 | } | 1025 | } |
1015 | 1026 | ||
@@ -1106,16 +1117,19 @@ static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon, | |||
1106 | } | 1117 | } |
1107 | 1118 | ||
1108 | static const struct sun4i_tcon_quirks sun4i_a10_quirks = { | 1119 | static const struct sun4i_tcon_quirks sun4i_a10_quirks = { |
1120 | .has_channel_0 = true, | ||
1109 | .has_channel_1 = true, | 1121 | .has_channel_1 = true, |
1110 | .set_mux = sun4i_a10_tcon_set_mux, | 1122 | .set_mux = sun4i_a10_tcon_set_mux, |
1111 | }; | 1123 | }; |
1112 | 1124 | ||
1113 | static const struct sun4i_tcon_quirks sun5i_a13_quirks = { | 1125 | static const struct sun4i_tcon_quirks sun5i_a13_quirks = { |
1126 | .has_channel_0 = true, | ||
1114 | .has_channel_1 = true, | 1127 | .has_channel_1 = true, |
1115 | .set_mux = sun5i_a13_tcon_set_mux, | 1128 | .set_mux = sun5i_a13_tcon_set_mux, |
1116 | }; | 1129 | }; |
1117 | 1130 | ||
1118 | static const struct sun4i_tcon_quirks sun6i_a31_quirks = { | 1131 | static const struct sun4i_tcon_quirks sun6i_a31_quirks = { |
1132 | .has_channel_0 = true, | ||
1119 | .has_channel_1 = true, | 1133 | .has_channel_1 = true, |
1120 | .has_lvds_alt = true, | 1134 | .has_lvds_alt = true, |
1121 | .needs_de_be_mux = true, | 1135 | .needs_de_be_mux = true, |
@@ -1123,26 +1137,33 @@ static const struct sun4i_tcon_quirks sun6i_a31_quirks = { | |||
1123 | }; | 1137 | }; |
1124 | 1138 | ||
1125 | static const struct sun4i_tcon_quirks sun6i_a31s_quirks = { | 1139 | static const struct sun4i_tcon_quirks sun6i_a31s_quirks = { |
1140 | .has_channel_0 = true, | ||
1126 | .has_channel_1 = true, | 1141 | .has_channel_1 = true, |
1127 | .needs_de_be_mux = true, | 1142 | .needs_de_be_mux = true, |
1128 | }; | 1143 | }; |
1129 | 1144 | ||
1130 | static const struct sun4i_tcon_quirks sun7i_a20_quirks = { | 1145 | static const struct sun4i_tcon_quirks sun7i_a20_quirks = { |
1146 | .has_channel_0 = true, | ||
1131 | .has_channel_1 = true, | 1147 | .has_channel_1 = true, |
1132 | /* Same display pipeline structure as A10 */ | 1148 | /* Same display pipeline structure as A10 */ |
1133 | .set_mux = sun4i_a10_tcon_set_mux, | 1149 | .set_mux = sun4i_a10_tcon_set_mux, |
1134 | }; | 1150 | }; |
1135 | 1151 | ||
1136 | static const struct sun4i_tcon_quirks sun8i_a33_quirks = { | 1152 | static const struct sun4i_tcon_quirks sun8i_a33_quirks = { |
1153 | .has_channel_0 = true, | ||
1137 | .has_lvds_alt = true, | 1154 | .has_lvds_alt = true, |
1138 | }; | 1155 | }; |
1139 | 1156 | ||
1140 | static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = { | 1157 | static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = { |
1141 | /* nothing is supported */ | 1158 | .has_channel_0 = true, |
1159 | }; | ||
1160 | |||
1161 | static const struct sun4i_tcon_quirks sun8i_a83t_tv_quirks = { | ||
1162 | .has_channel_1 = true, | ||
1142 | }; | 1163 | }; |
1143 | 1164 | ||
1144 | static const struct sun4i_tcon_quirks sun8i_v3s_quirks = { | 1165 | static const struct sun4i_tcon_quirks sun8i_v3s_quirks = { |
1145 | /* nothing is supported */ | 1166 | .has_channel_0 = true, |
1146 | }; | 1167 | }; |
1147 | 1168 | ||
1148 | /* sun4i_drv uses this list to check if a device node is a TCON */ | 1169 | /* sun4i_drv uses this list to check if a device node is a TCON */ |
@@ -1154,6 +1175,7 @@ const struct of_device_id sun4i_tcon_of_table[] = { | |||
1154 | { .compatible = "allwinner,sun7i-a20-tcon", .data = &sun7i_a20_quirks }, | 1175 | { .compatible = "allwinner,sun7i-a20-tcon", .data = &sun7i_a20_quirks }, |
1155 | { .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks }, | 1176 | { .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks }, |
1156 | { .compatible = "allwinner,sun8i-a83t-tcon-lcd", .data = &sun8i_a83t_lcd_quirks }, | 1177 | { .compatible = "allwinner,sun8i-a83t-tcon-lcd", .data = &sun8i_a83t_lcd_quirks }, |
1178 | { .compatible = "allwinner,sun8i-a83t-tcon-tv", .data = &sun8i_a83t_tv_quirks }, | ||
1157 | { .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks }, | 1179 | { .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks }, |
1158 | { } | 1180 | { } |
1159 | }; | 1181 | }; |
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h index b761c7b823c5..78d55e7cd2b3 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h | |||
@@ -172,6 +172,7 @@ | |||
172 | struct sun4i_tcon; | 172 | struct sun4i_tcon; |
173 | 173 | ||
174 | struct sun4i_tcon_quirks { | 174 | struct sun4i_tcon_quirks { |
175 | bool has_channel_0; /* a83t does not have channel 0 on second TCON */ | ||
175 | bool has_channel_1; /* a33 does not have channel 1 */ | 176 | bool has_channel_1; /* a33 does not have channel 1 */ |
176 | bool has_lvds_alt; /* Does the LVDS clock have a parent other than the TCON clock? */ | 177 | bool has_lvds_alt; /* Does the LVDS clock have a parent other than the TCON clock? */ |
177 | bool needs_de_be_mux; /* sun6i needs mux to select backend */ | 178 | bool needs_de_be_mux; /* sun6i needs mux to select backend */ |
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c new file mode 100644 index 000000000000..9f40a44b456b --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | |||
@@ -0,0 +1,196 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * Copyright (c) 2018 Jernej Skrabec <jernej.skrabec@siol.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/component.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/platform_device.h> | ||
9 | |||
10 | #include <drm/drm_of.h> | ||
11 | #include <drm/drmP.h> | ||
12 | #include <drm/drm_crtc_helper.h> | ||
13 | |||
14 | #include "sun8i_dw_hdmi.h" | ||
15 | |||
16 | static void sun8i_dw_hdmi_encoder_mode_set(struct drm_encoder *encoder, | ||
17 | struct drm_display_mode *mode, | ||
18 | struct drm_display_mode *adj_mode) | ||
19 | { | ||
20 | struct sun8i_dw_hdmi *hdmi = encoder_to_sun8i_dw_hdmi(encoder); | ||
21 | |||
22 | clk_set_rate(hdmi->clk_tmds, mode->crtc_clock * 1000); | ||
23 | } | ||
24 | |||
25 | static const struct drm_encoder_helper_funcs | ||
26 | sun8i_dw_hdmi_encoder_helper_funcs = { | ||
27 | .mode_set = sun8i_dw_hdmi_encoder_mode_set, | ||
28 | }; | ||
29 | |||
30 | static const struct drm_encoder_funcs sun8i_dw_hdmi_encoder_funcs = { | ||
31 | .destroy = drm_encoder_cleanup, | ||
32 | }; | ||
33 | |||
34 | static enum drm_mode_status | ||
35 | sun8i_dw_hdmi_mode_valid(struct drm_connector *connector, | ||
36 | const struct drm_display_mode *mode) | ||
37 | { | ||
38 | if (mode->clock > 297000) | ||
39 | return MODE_CLOCK_HIGH; | ||
40 | |||
41 | return MODE_OK; | ||
42 | } | ||
43 | |||
44 | static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, | ||
45 | void *data) | ||
46 | { | ||
47 | struct platform_device *pdev = to_platform_device(dev); | ||
48 | struct dw_hdmi_plat_data *plat_data; | ||
49 | struct drm_device *drm = data; | ||
50 | struct device_node *phy_node; | ||
51 | struct drm_encoder *encoder; | ||
52 | struct sun8i_dw_hdmi *hdmi; | ||
53 | int ret; | ||
54 | |||
55 | if (!pdev->dev.of_node) | ||
56 | return -ENODEV; | ||
57 | |||
58 | hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); | ||
59 | if (!hdmi) | ||
60 | return -ENOMEM; | ||
61 | |||
62 | plat_data = &hdmi->plat_data; | ||
63 | hdmi->dev = &pdev->dev; | ||
64 | encoder = &hdmi->encoder; | ||
65 | |||
66 | encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); | ||
67 | /* | ||
68 | * If we failed to find the CRTC(s) which this encoder is | ||
69 | * supposed to be connected to, it's because the CRTC has | ||
70 | * not been registered yet. Defer probing, and hope that | ||
71 | * the required CRTC is added later. | ||
72 | */ | ||
73 | if (encoder->possible_crtcs == 0) | ||
74 | return -EPROBE_DEFER; | ||
75 | |||
76 | hdmi->rst_ctrl = devm_reset_control_get(dev, "ctrl"); | ||
77 | if (IS_ERR(hdmi->rst_ctrl)) { | ||
78 | dev_err(dev, "Could not get ctrl reset control\n"); | ||
79 | return PTR_ERR(hdmi->rst_ctrl); | ||
80 | } | ||
81 | |||
82 | hdmi->clk_tmds = devm_clk_get(dev, "tmds"); | ||
83 | if (IS_ERR(hdmi->clk_tmds)) { | ||
84 | dev_err(dev, "Couldn't get the tmds clock\n"); | ||
85 | return PTR_ERR(hdmi->clk_tmds); | ||
86 | } | ||
87 | |||
88 | ret = reset_control_deassert(hdmi->rst_ctrl); | ||
89 | if (ret) { | ||
90 | dev_err(dev, "Could not deassert ctrl reset control\n"); | ||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | ret = clk_prepare_enable(hdmi->clk_tmds); | ||
95 | if (ret) { | ||
96 | dev_err(dev, "Could not enable tmds clock\n"); | ||
97 | goto err_assert_ctrl_reset; | ||
98 | } | ||
99 | |||
100 | phy_node = of_parse_phandle(dev->of_node, "phys", 0); | ||
101 | if (!phy_node) { | ||
102 | dev_err(dev, "Can't found PHY phandle\n"); | ||
103 | goto err_disable_clk_tmds; | ||
104 | } | ||
105 | |||
106 | ret = sun8i_hdmi_phy_probe(hdmi, phy_node); | ||
107 | of_node_put(phy_node); | ||
108 | if (ret) { | ||
109 | dev_err(dev, "Couldn't get the HDMI PHY\n"); | ||
110 | goto err_disable_clk_tmds; | ||
111 | } | ||
112 | |||
113 | drm_encoder_helper_add(encoder, &sun8i_dw_hdmi_encoder_helper_funcs); | ||
114 | drm_encoder_init(drm, encoder, &sun8i_dw_hdmi_encoder_funcs, | ||
115 | DRM_MODE_ENCODER_TMDS, NULL); | ||
116 | |||
117 | sun8i_hdmi_phy_init(hdmi->phy); | ||
118 | |||
119 | plat_data->mode_valid = &sun8i_dw_hdmi_mode_valid; | ||
120 | plat_data->phy_ops = sun8i_hdmi_phy_get_ops(); | ||
121 | plat_data->phy_name = "sun8i_dw_hdmi_phy"; | ||
122 | plat_data->phy_data = hdmi->phy; | ||
123 | |||
124 | platform_set_drvdata(pdev, hdmi); | ||
125 | |||
126 | hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); | ||
127 | |||
128 | /* | ||
129 | * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), | ||
130 | * which would have called the encoder cleanup. Do it manually. | ||
131 | */ | ||
132 | if (IS_ERR(hdmi->hdmi)) { | ||
133 | ret = PTR_ERR(hdmi->hdmi); | ||
134 | goto cleanup_encoder; | ||
135 | } | ||
136 | |||
137 | return 0; | ||
138 | |||
139 | cleanup_encoder: | ||
140 | drm_encoder_cleanup(encoder); | ||
141 | sun8i_hdmi_phy_remove(hdmi); | ||
142 | err_disable_clk_tmds: | ||
143 | clk_disable_unprepare(hdmi->clk_tmds); | ||
144 | err_assert_ctrl_reset: | ||
145 | reset_control_assert(hdmi->rst_ctrl); | ||
146 | |||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | static void sun8i_dw_hdmi_unbind(struct device *dev, struct device *master, | ||
151 | void *data) | ||
152 | { | ||
153 | struct sun8i_dw_hdmi *hdmi = dev_get_drvdata(dev); | ||
154 | |||
155 | dw_hdmi_unbind(hdmi->hdmi); | ||
156 | sun8i_hdmi_phy_remove(hdmi); | ||
157 | clk_disable_unprepare(hdmi->clk_tmds); | ||
158 | reset_control_assert(hdmi->rst_ctrl); | ||
159 | } | ||
160 | |||
161 | static const struct component_ops sun8i_dw_hdmi_ops = { | ||
162 | .bind = sun8i_dw_hdmi_bind, | ||
163 | .unbind = sun8i_dw_hdmi_unbind, | ||
164 | }; | ||
165 | |||
166 | static int sun8i_dw_hdmi_probe(struct platform_device *pdev) | ||
167 | { | ||
168 | return component_add(&pdev->dev, &sun8i_dw_hdmi_ops); | ||
169 | } | ||
170 | |||
171 | static int sun8i_dw_hdmi_remove(struct platform_device *pdev) | ||
172 | { | ||
173 | component_del(&pdev->dev, &sun8i_dw_hdmi_ops); | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static const struct of_device_id sun8i_dw_hdmi_dt_ids[] = { | ||
179 | { .compatible = "allwinner,sun8i-a83t-dw-hdmi" }, | ||
180 | { /* sentinel */ }, | ||
181 | }; | ||
182 | MODULE_DEVICE_TABLE(of, sun8i_dw_hdmi_dt_ids); | ||
183 | |||
184 | struct platform_driver sun8i_dw_hdmi_pltfm_driver = { | ||
185 | .probe = sun8i_dw_hdmi_probe, | ||
186 | .remove = sun8i_dw_hdmi_remove, | ||
187 | .driver = { | ||
188 | .name = "sun8i-dw-hdmi", | ||
189 | .of_match_table = sun8i_dw_hdmi_dt_ids, | ||
190 | }, | ||
191 | }; | ||
192 | module_platform_driver(sun8i_dw_hdmi_pltfm_driver); | ||
193 | |||
194 | MODULE_AUTHOR("Jernej Skrabec <jernej.skrabec@siol.net>"); | ||
195 | MODULE_DESCRIPTION("Allwinner DW HDMI bridge"); | ||
196 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h new file mode 100644 index 000000000000..d8d0684fc8aa --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0+ */ | ||
2 | /* | ||
3 | * Copyright (C) 2018 Jernej Skrabec <jernej.skrabec@siol.net> | ||
4 | */ | ||
5 | |||
6 | #ifndef _SUN8I_DW_HDMI_H_ | ||
7 | #define _SUN8I_DW_HDMI_H_ | ||
8 | |||
9 | #include <drm/bridge/dw_hdmi.h> | ||
10 | #include <drm/drm_encoder.h> | ||
11 | #include <linux/clk.h> | ||
12 | #include <linux/regmap.h> | ||
13 | #include <linux/reset.h> | ||
14 | |||
15 | struct sun8i_hdmi_phy { | ||
16 | struct clk *clk_bus; | ||
17 | struct clk *clk_mod; | ||
18 | struct regmap *regs; | ||
19 | struct reset_control *rst_phy; | ||
20 | }; | ||
21 | |||
22 | struct sun8i_dw_hdmi { | ||
23 | struct clk *clk_tmds; | ||
24 | struct device *dev; | ||
25 | struct dw_hdmi *hdmi; | ||
26 | struct drm_encoder encoder; | ||
27 | struct sun8i_hdmi_phy *phy; | ||
28 | struct dw_hdmi_plat_data plat_data; | ||
29 | struct reset_control *rst_ctrl; | ||
30 | }; | ||
31 | |||
32 | static inline struct sun8i_dw_hdmi * | ||
33 | encoder_to_sun8i_dw_hdmi(struct drm_encoder *encoder) | ||
34 | { | ||
35 | return container_of(encoder, struct sun8i_dw_hdmi, encoder); | ||
36 | } | ||
37 | |||
38 | int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node); | ||
39 | void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi); | ||
40 | |||
41 | void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy); | ||
42 | const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void); | ||
43 | |||
44 | #endif /* _SUN8I_DW_HDMI_H_ */ | ||
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c new file mode 100644 index 000000000000..e5bfcdd43ec9 --- /dev/null +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | |||
@@ -0,0 +1,270 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * Copyright (c) 2018 Jernej Skrabec <jernej.skrabec@siol.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/of_address.h> | ||
7 | |||
8 | #include "sun8i_dw_hdmi.h" | ||
9 | |||
10 | #define SUN8I_HDMI_PHY_DBG_CTRL_REG 0x0000 | ||
11 | #define SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK BIT(0) | ||
12 | #define SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK GENMASK(15, 8) | ||
13 | #define SUN8I_HDMI_PHY_DBG_CTRL_POL(val) (val << 8) | ||
14 | #define SUN8I_HDMI_PHY_DBG_CTRL_ADDR_MASK GENMASK(23, 16) | ||
15 | #define SUN8I_HDMI_PHY_DBG_CTRL_ADDR(addr) (addr << 16) | ||
16 | |||
17 | #define SUN8I_HDMI_PHY_REXT_CTRL_REG 0x0004 | ||
18 | #define SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN BIT(31) | ||
19 | |||
20 | #define SUN8I_HDMI_PHY_READ_EN_REG 0x0010 | ||
21 | #define SUN8I_HDMI_PHY_READ_EN_MAGIC 0x54524545 | ||
22 | |||
23 | #define SUN8I_HDMI_PHY_UNSCRAMBLE_REG 0x0014 | ||
24 | #define SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC 0x42494E47 | ||
25 | |||
26 | /* | ||
27 | * Address can be actually any value. Here is set to same value as | ||
28 | * it is set in BSP driver. | ||
29 | */ | ||
30 | #define I2C_ADDR 0x69 | ||
31 | |||
32 | static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data, | ||
33 | struct drm_display_mode *mode) | ||
34 | { | ||
35 | struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data; | ||
36 | u32 val = 0; | ||
37 | |||
38 | if ((mode->flags & DRM_MODE_FLAG_NHSYNC) && | ||
39 | (mode->flags & DRM_MODE_FLAG_NHSYNC)) { | ||
40 | val = 0x03; | ||
41 | } | ||
42 | |||
43 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG, | ||
44 | SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK, | ||
45 | SUN8I_HDMI_PHY_DBG_CTRL_POL(val)); | ||
46 | |||
47 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_REXT_CTRL_REG, | ||
48 | SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN, | ||
49 | SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN); | ||
50 | |||
51 | /* power down */ | ||
52 | dw_hdmi_phy_gen2_txpwron(hdmi, 0); | ||
53 | dw_hdmi_phy_gen2_pddq(hdmi, 1); | ||
54 | |||
55 | dw_hdmi_phy_reset(hdmi); | ||
56 | |||
57 | dw_hdmi_phy_gen2_pddq(hdmi, 0); | ||
58 | |||
59 | dw_hdmi_phy_i2c_set_addr(hdmi, I2C_ADDR); | ||
60 | |||
61 | /* | ||
62 | * Values are taken from BSP HDMI driver. Although AW didn't | ||
63 | * release any documentation, explanation of this values can | ||
64 | * be found in i.MX 6Dual/6Quad Reference Manual. | ||
65 | */ | ||
66 | if (mode->crtc_clock <= 27000) { | ||
67 | dw_hdmi_phy_i2c_write(hdmi, 0x01e0, 0x06); | ||
68 | dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x15); | ||
69 | dw_hdmi_phy_i2c_write(hdmi, 0x08da, 0x10); | ||
70 | dw_hdmi_phy_i2c_write(hdmi, 0x0007, 0x19); | ||
71 | dw_hdmi_phy_i2c_write(hdmi, 0x0318, 0x0e); | ||
72 | dw_hdmi_phy_i2c_write(hdmi, 0x8009, 0x09); | ||
73 | } else if (mode->crtc_clock <= 74250) { | ||
74 | dw_hdmi_phy_i2c_write(hdmi, 0x0540, 0x06); | ||
75 | dw_hdmi_phy_i2c_write(hdmi, 0x0005, 0x15); | ||
76 | dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10); | ||
77 | dw_hdmi_phy_i2c_write(hdmi, 0x0007, 0x19); | ||
78 | dw_hdmi_phy_i2c_write(hdmi, 0x02b5, 0x0e); | ||
79 | dw_hdmi_phy_i2c_write(hdmi, 0x8009, 0x09); | ||
80 | } else if (mode->crtc_clock <= 148500) { | ||
81 | dw_hdmi_phy_i2c_write(hdmi, 0x04a0, 0x06); | ||
82 | dw_hdmi_phy_i2c_write(hdmi, 0x000a, 0x15); | ||
83 | dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10); | ||
84 | dw_hdmi_phy_i2c_write(hdmi, 0x0002, 0x19); | ||
85 | dw_hdmi_phy_i2c_write(hdmi, 0x0021, 0x0e); | ||
86 | dw_hdmi_phy_i2c_write(hdmi, 0x8029, 0x09); | ||
87 | } else { | ||
88 | dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x06); | ||
89 | dw_hdmi_phy_i2c_write(hdmi, 0x000f, 0x15); | ||
90 | dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10); | ||
91 | dw_hdmi_phy_i2c_write(hdmi, 0x0002, 0x19); | ||
92 | dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x0e); | ||
93 | dw_hdmi_phy_i2c_write(hdmi, 0x802b, 0x09); | ||
94 | } | ||
95 | |||
96 | dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x1e); | ||
97 | dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); | ||
98 | dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x17); | ||
99 | |||
100 | dw_hdmi_phy_gen2_txpwron(hdmi, 1); | ||
101 | |||
102 | return 0; | ||
103 | }; | ||
104 | |||
105 | static void sun8i_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data) | ||
106 | { | ||
107 | struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data; | ||
108 | |||
109 | dw_hdmi_phy_gen2_txpwron(hdmi, 0); | ||
110 | dw_hdmi_phy_gen2_pddq(hdmi, 1); | ||
111 | |||
112 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_REXT_CTRL_REG, | ||
113 | SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN, 0); | ||
114 | } | ||
115 | |||
116 | static const struct dw_hdmi_phy_ops sun8i_hdmi_phy_ops = { | ||
117 | .init = &sun8i_hdmi_phy_config, | ||
118 | .disable = &sun8i_hdmi_phy_disable, | ||
119 | .read_hpd = &dw_hdmi_phy_read_hpd, | ||
120 | .update_hpd = &dw_hdmi_phy_update_hpd, | ||
121 | .setup_hpd = &dw_hdmi_phy_setup_hpd, | ||
122 | }; | ||
123 | |||
124 | void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy) | ||
125 | { | ||
126 | /* enable read access to HDMI controller */ | ||
127 | regmap_write(phy->regs, SUN8I_HDMI_PHY_READ_EN_REG, | ||
128 | SUN8I_HDMI_PHY_READ_EN_MAGIC); | ||
129 | |||
130 | /* unscramble register offsets */ | ||
131 | regmap_write(phy->regs, SUN8I_HDMI_PHY_UNSCRAMBLE_REG, | ||
132 | SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC); | ||
133 | |||
134 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG, | ||
135 | SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK, | ||
136 | SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK); | ||
137 | |||
138 | /* | ||
139 | * Set PHY I2C address. It must match to the address set by | ||
140 | * dw_hdmi_phy_set_slave_addr(). | ||
141 | */ | ||
142 | regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG, | ||
143 | SUN8I_HDMI_PHY_DBG_CTRL_ADDR_MASK, | ||
144 | SUN8I_HDMI_PHY_DBG_CTRL_ADDR(I2C_ADDR)); | ||
145 | } | ||
146 | |||
147 | const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void) | ||
148 | { | ||
149 | return &sun8i_hdmi_phy_ops; | ||
150 | } | ||
151 | |||
152 | static struct regmap_config sun8i_hdmi_phy_regmap_config = { | ||
153 | .reg_bits = 32, | ||
154 | .val_bits = 32, | ||
155 | .reg_stride = 4, | ||
156 | .max_register = SUN8I_HDMI_PHY_UNSCRAMBLE_REG, | ||
157 | .name = "phy" | ||
158 | }; | ||
159 | |||
160 | static const struct of_device_id sun8i_hdmi_phy_of_table[] = { | ||
161 | { .compatible = "allwinner,sun8i-a83t-hdmi-phy" }, | ||
162 | { /* sentinel */ } | ||
163 | }; | ||
164 | |||
165 | int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node) | ||
166 | { | ||
167 | struct device *dev = hdmi->dev; | ||
168 | struct sun8i_hdmi_phy *phy; | ||
169 | struct resource res; | ||
170 | void __iomem *regs; | ||
171 | int ret; | ||
172 | |||
173 | if (!of_match_node(sun8i_hdmi_phy_of_table, node)) { | ||
174 | dev_err(dev, "Incompatible HDMI PHY\n"); | ||
175 | return -EINVAL; | ||
176 | } | ||
177 | |||
178 | phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); | ||
179 | if (!phy) | ||
180 | return -ENOMEM; | ||
181 | |||
182 | ret = of_address_to_resource(node, 0, &res); | ||
183 | if (ret) { | ||
184 | dev_err(dev, "phy: Couldn't get our resources\n"); | ||
185 | return ret; | ||
186 | } | ||
187 | |||
188 | regs = devm_ioremap_resource(dev, &res); | ||
189 | if (IS_ERR(regs)) { | ||
190 | dev_err(dev, "Couldn't map the HDMI PHY registers\n"); | ||
191 | return PTR_ERR(regs); | ||
192 | } | ||
193 | |||
194 | phy->regs = devm_regmap_init_mmio(dev, regs, | ||
195 | &sun8i_hdmi_phy_regmap_config); | ||
196 | if (IS_ERR(phy->regs)) { | ||
197 | dev_err(dev, "Couldn't create the HDMI PHY regmap\n"); | ||
198 | return PTR_ERR(phy->regs); | ||
199 | } | ||
200 | |||
201 | phy->clk_bus = of_clk_get_by_name(node, "bus"); | ||
202 | if (IS_ERR(phy->clk_bus)) { | ||
203 | dev_err(dev, "Could not get bus clock\n"); | ||
204 | return PTR_ERR(phy->clk_bus); | ||
205 | } | ||
206 | |||
207 | phy->clk_mod = of_clk_get_by_name(node, "mod"); | ||
208 | if (IS_ERR(phy->clk_mod)) { | ||
209 | dev_err(dev, "Could not get mod clock\n"); | ||
210 | ret = PTR_ERR(phy->clk_mod); | ||
211 | goto err_put_clk_bus; | ||
212 | } | ||
213 | |||
214 | phy->rst_phy = of_reset_control_get_shared(node, "phy"); | ||
215 | if (IS_ERR(phy->rst_phy)) { | ||
216 | dev_err(dev, "Could not get phy reset control\n"); | ||
217 | ret = PTR_ERR(phy->rst_phy); | ||
218 | goto err_put_clk_mod; | ||
219 | } | ||
220 | |||
221 | ret = reset_control_deassert(phy->rst_phy); | ||
222 | if (ret) { | ||
223 | dev_err(dev, "Cannot deassert phy reset control: %d\n", ret); | ||
224 | goto err_put_rst_phy; | ||
225 | } | ||
226 | |||
227 | ret = clk_prepare_enable(phy->clk_bus); | ||
228 | if (ret) { | ||
229 | dev_err(dev, "Cannot enable bus clock: %d\n", ret); | ||
230 | goto err_deassert_rst_phy; | ||
231 | } | ||
232 | |||
233 | ret = clk_prepare_enable(phy->clk_mod); | ||
234 | if (ret) { | ||
235 | dev_err(dev, "Cannot enable mod clock: %d\n", ret); | ||
236 | goto err_disable_clk_bus; | ||
237 | } | ||
238 | |||
239 | hdmi->phy = phy; | ||
240 | |||
241 | return 0; | ||
242 | |||
243 | err_disable_clk_bus: | ||
244 | clk_disable_unprepare(phy->clk_bus); | ||
245 | err_deassert_rst_phy: | ||
246 | reset_control_assert(phy->rst_phy); | ||
247 | err_put_rst_phy: | ||
248 | reset_control_put(phy->rst_phy); | ||
249 | err_put_clk_mod: | ||
250 | clk_put(phy->clk_mod); | ||
251 | err_put_clk_bus: | ||
252 | clk_put(phy->clk_bus); | ||
253 | |||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi) | ||
258 | { | ||
259 | struct sun8i_hdmi_phy *phy = hdmi->phy; | ||
260 | |||
261 | clk_disable_unprepare(phy->clk_mod); | ||
262 | clk_disable_unprepare(phy->clk_bus); | ||
263 | |||
264 | reset_control_assert(phy->rst_phy); | ||
265 | |||
266 | reset_control_put(phy->rst_phy); | ||
267 | |||
268 | clk_put(phy->clk_mod); | ||
269 | clk_put(phy->clk_bus); | ||
270 | } | ||
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index 2cbb2de6d39c..9b0256d31a61 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c | |||
@@ -485,6 +485,13 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = { | |||
485 | .vi_num = 1, | 485 | .vi_num = 1, |
486 | }; | 486 | }; |
487 | 487 | ||
488 | static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = { | ||
489 | .ccsc = 1, | ||
490 | .scaler_mask = 0x3, | ||
491 | .ui_num = 1, | ||
492 | .vi_num = 1, | ||
493 | }; | ||
494 | |||
488 | static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = { | 495 | static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = { |
489 | .vi_num = 2, | 496 | .vi_num = 2, |
490 | .ui_num = 1, | 497 | .ui_num = 1, |
@@ -499,6 +506,10 @@ static const struct of_device_id sun8i_mixer_of_table[] = { | |||
499 | .data = &sun8i_a83t_mixer0_cfg, | 506 | .data = &sun8i_a83t_mixer0_cfg, |
500 | }, | 507 | }, |
501 | { | 508 | { |
509 | .compatible = "allwinner,sun8i-a83t-de2-mixer-1", | ||
510 | .data = &sun8i_a83t_mixer1_cfg, | ||
511 | }, | ||
512 | { | ||
502 | .compatible = "allwinner,sun8i-v3s-de2-mixer", | 513 | .compatible = "allwinner,sun8i-v3s-de2-mixer", |
503 | .data = &sun8i_v3s_mixer_cfg, | 514 | .data = &sun8i_v3s_mixer_cfg, |
504 | }, | 515 | }, |
diff --git a/drivers/gpu/drm/tinydrm/Kconfig b/drivers/gpu/drm/tinydrm/Kconfig index b0e567d416b3..13339be843bc 100644 --- a/drivers/gpu/drm/tinydrm/Kconfig +++ b/drivers/gpu/drm/tinydrm/Kconfig | |||
@@ -3,8 +3,6 @@ menuconfig DRM_TINYDRM | |||
3 | depends on DRM | 3 | depends on DRM |
4 | select DRM_KMS_HELPER | 4 | select DRM_KMS_HELPER |
5 | select DRM_KMS_CMA_HELPER | 5 | select DRM_KMS_CMA_HELPER |
6 | select BACKLIGHT_LCD_SUPPORT | ||
7 | select BACKLIGHT_CLASS_DEVICE | ||
8 | help | 6 | help |
9 | Choose this option if you have a tinydrm supported display. | 7 | Choose this option if you have a tinydrm supported display. |
10 | If M is selected the module will be called tinydrm. | 8 | If M is selected the module will be called tinydrm. |
diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c index bf96072d1b97..d1c3ce9ab294 100644 --- a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c +++ b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c | |||
@@ -236,101 +236,6 @@ void tinydrm_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb, | |||
236 | } | 236 | } |
237 | EXPORT_SYMBOL(tinydrm_xrgb8888_to_gray8); | 237 | EXPORT_SYMBOL(tinydrm_xrgb8888_to_gray8); |
238 | 238 | ||
239 | /** | ||
240 | * tinydrm_of_find_backlight - Find backlight device in device-tree | ||
241 | * @dev: Device | ||
242 | * | ||
243 | * This function looks for a DT node pointed to by a property named 'backlight' | ||
244 | * and uses of_find_backlight_by_node() to get the backlight device. | ||
245 | * Additionally if the brightness property is zero, it is set to | ||
246 | * max_brightness. | ||
247 | * | ||
248 | * Returns: | ||
249 | * NULL if there's no backlight property. | ||
250 | * Error pointer -EPROBE_DEFER if the DT node is found, but no backlight device | ||
251 | * is found. | ||
252 | * If the backlight device is found, a pointer to the structure is returned. | ||
253 | */ | ||
254 | struct backlight_device *tinydrm_of_find_backlight(struct device *dev) | ||
255 | { | ||
256 | struct backlight_device *backlight; | ||
257 | struct device_node *np; | ||
258 | |||
259 | np = of_parse_phandle(dev->of_node, "backlight", 0); | ||
260 | if (!np) | ||
261 | return NULL; | ||
262 | |||
263 | backlight = of_find_backlight_by_node(np); | ||
264 | of_node_put(np); | ||
265 | |||
266 | if (!backlight) | ||
267 | return ERR_PTR(-EPROBE_DEFER); | ||
268 | |||
269 | if (!backlight->props.brightness) { | ||
270 | backlight->props.brightness = backlight->props.max_brightness; | ||
271 | DRM_DEBUG_KMS("Backlight brightness set to %d\n", | ||
272 | backlight->props.brightness); | ||
273 | } | ||
274 | |||
275 | return backlight; | ||
276 | } | ||
277 | EXPORT_SYMBOL(tinydrm_of_find_backlight); | ||
278 | |||
279 | /** | ||
280 | * tinydrm_enable_backlight - Enable backlight helper | ||
281 | * @backlight: Backlight device | ||
282 | * | ||
283 | * Returns: | ||
284 | * Zero on success, negative error code on failure. | ||
285 | */ | ||
286 | int tinydrm_enable_backlight(struct backlight_device *backlight) | ||
287 | { | ||
288 | unsigned int old_state; | ||
289 | int ret; | ||
290 | |||
291 | if (!backlight) | ||
292 | return 0; | ||
293 | |||
294 | old_state = backlight->props.state; | ||
295 | backlight->props.state &= ~BL_CORE_FBBLANK; | ||
296 | DRM_DEBUG_KMS("Backlight state: 0x%x -> 0x%x\n", old_state, | ||
297 | backlight->props.state); | ||
298 | |||
299 | ret = backlight_update_status(backlight); | ||
300 | if (ret) | ||
301 | DRM_ERROR("Failed to enable backlight %d\n", ret); | ||
302 | |||
303 | return ret; | ||
304 | } | ||
305 | EXPORT_SYMBOL(tinydrm_enable_backlight); | ||
306 | |||
307 | /** | ||
308 | * tinydrm_disable_backlight - Disable backlight helper | ||
309 | * @backlight: Backlight device | ||
310 | * | ||
311 | * Returns: | ||
312 | * Zero on success, negative error code on failure. | ||
313 | */ | ||
314 | int tinydrm_disable_backlight(struct backlight_device *backlight) | ||
315 | { | ||
316 | unsigned int old_state; | ||
317 | int ret; | ||
318 | |||
319 | if (!backlight) | ||
320 | return 0; | ||
321 | |||
322 | old_state = backlight->props.state; | ||
323 | backlight->props.state |= BL_CORE_FBBLANK; | ||
324 | DRM_DEBUG_KMS("Backlight state: 0x%x -> 0x%x\n", old_state, | ||
325 | backlight->props.state); | ||
326 | ret = backlight_update_status(backlight); | ||
327 | if (ret) | ||
328 | DRM_ERROR("Failed to disable backlight %d\n", ret); | ||
329 | |||
330 | return ret; | ||
331 | } | ||
332 | EXPORT_SYMBOL(tinydrm_disable_backlight); | ||
333 | |||
334 | #if IS_ENABLED(CONFIG_SPI) | 239 | #if IS_ENABLED(CONFIG_SPI) |
335 | 240 | ||
336 | /** | 241 | /** |
diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c index 79cb5af5abac..d8ed6e6f8e05 100644 --- a/drivers/gpu/drm/tinydrm/mi0283qt.c +++ b/drivers/gpu/drm/tinydrm/mi0283qt.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * (at your option) any later version. | 9 | * (at your option) any later version. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/backlight.h> | ||
12 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
13 | #include <linux/gpio/consumer.h> | 14 | #include <linux/gpio/consumer.h> |
14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
@@ -195,7 +196,7 @@ static int mi0283qt_probe(struct spi_device *spi) | |||
195 | if (IS_ERR(mipi->regulator)) | 196 | if (IS_ERR(mipi->regulator)) |
196 | return PTR_ERR(mipi->regulator); | 197 | return PTR_ERR(mipi->regulator); |
197 | 198 | ||
198 | mipi->backlight = tinydrm_of_find_backlight(dev); | 199 | mipi->backlight = devm_of_find_backlight(dev); |
199 | if (IS_ERR(mipi->backlight)) | 200 | if (IS_ERR(mipi->backlight)) |
200 | return PTR_ERR(mipi->backlight); | 201 | return PTR_ERR(mipi->backlight); |
201 | 202 | ||
diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c index 75dd65c57e74..9e903812b573 100644 --- a/drivers/gpu/drm/tinydrm/mipi-dbi.c +++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c | |||
@@ -286,7 +286,7 @@ void mipi_dbi_enable_flush(struct mipi_dbi *mipi) | |||
286 | if (fb) | 286 | if (fb) |
287 | fb->funcs->dirty(fb, NULL, 0, 0, NULL, 0); | 287 | fb->funcs->dirty(fb, NULL, 0, 0, NULL, 0); |
288 | 288 | ||
289 | tinydrm_enable_backlight(mipi->backlight); | 289 | backlight_enable(mipi->backlight); |
290 | } | 290 | } |
291 | EXPORT_SYMBOL(mipi_dbi_enable_flush); | 291 | EXPORT_SYMBOL(mipi_dbi_enable_flush); |
292 | 292 | ||
@@ -325,7 +325,7 @@ void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe) | |||
325 | mipi->enabled = false; | 325 | mipi->enabled = false; |
326 | 326 | ||
327 | if (mipi->backlight) | 327 | if (mipi->backlight) |
328 | tinydrm_disable_backlight(mipi->backlight); | 328 | backlight_disable(mipi->backlight); |
329 | else | 329 | else |
330 | mipi_dbi_blank(mipi); | 330 | mipi_dbi_blank(mipi); |
331 | 331 | ||
diff --git a/drivers/gpu/drm/tinydrm/st7735r.c b/drivers/gpu/drm/tinydrm/st7735r.c index 08b4fb18edb6..67d197ecfc4b 100644 --- a/drivers/gpu/drm/tinydrm/st7735r.c +++ b/drivers/gpu/drm/tinydrm/st7735r.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * Copyright 2017 David Lechner <david@lechnology.com> | 5 | * Copyright 2017 David Lechner <david@lechnology.com> |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/backlight.h> | ||
8 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
9 | #include <linux/dma-buf.h> | 10 | #include <linux/dma-buf.h> |
10 | #include <linux/gpio/consumer.h> | 11 | #include <linux/gpio/consumer.h> |
@@ -163,7 +164,7 @@ static int st7735r_probe(struct spi_device *spi) | |||
163 | return PTR_ERR(dc); | 164 | return PTR_ERR(dc); |
164 | } | 165 | } |
165 | 166 | ||
166 | mipi->backlight = tinydrm_of_find_backlight(dev); | 167 | mipi->backlight = devm_of_find_backlight(dev); |
167 | if (IS_ERR(mipi->backlight)) | 168 | if (IS_ERR(mipi->backlight)) |
168 | return PTR_ERR(mipi->backlight); | 169 | return PTR_ERR(mipi->backlight); |
169 | 170 | ||
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 8049e7656daa..deb824bef6e2 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c | |||
@@ -580,6 +580,79 @@ struct backlight_device *of_find_backlight_by_node(struct device_node *node) | |||
580 | EXPORT_SYMBOL(of_find_backlight_by_node); | 580 | EXPORT_SYMBOL(of_find_backlight_by_node); |
581 | #endif | 581 | #endif |
582 | 582 | ||
583 | /** | ||
584 | * of_find_backlight - Get backlight device | ||
585 | * @dev: Device | ||
586 | * | ||
587 | * This function looks for a property named 'backlight' on the DT node | ||
588 | * connected to @dev and looks up the backlight device. | ||
589 | * | ||
590 | * Call backlight_put() to drop the reference on the backlight device. | ||
591 | * | ||
592 | * Returns: | ||
593 | * A pointer to the backlight device if found. | ||
594 | * Error pointer -EPROBE_DEFER if the DT property is set, but no backlight | ||
595 | * device is found. | ||
596 | * NULL if there's no backlight property. | ||
597 | */ | ||
598 | struct backlight_device *of_find_backlight(struct device *dev) | ||
599 | { | ||
600 | struct backlight_device *bd = NULL; | ||
601 | struct device_node *np; | ||
602 | |||
603 | if (!dev) | ||
604 | return NULL; | ||
605 | |||
606 | if (IS_ENABLED(CONFIG_OF) && dev->of_node) { | ||
607 | np = of_parse_phandle(dev->of_node, "backlight", 0); | ||
608 | if (np) { | ||
609 | bd = of_find_backlight_by_node(np); | ||
610 | of_node_put(np); | ||
611 | if (!bd) | ||
612 | return ERR_PTR(-EPROBE_DEFER); | ||
613 | /* | ||
614 | * Note: gpio_backlight uses brightness as | ||
615 | * power state during probe | ||
616 | */ | ||
617 | if (!bd->props.brightness) | ||
618 | bd->props.brightness = bd->props.max_brightness; | ||
619 | } | ||
620 | } | ||
621 | |||
622 | return bd; | ||
623 | } | ||
624 | EXPORT_SYMBOL(of_find_backlight); | ||
625 | |||
626 | static void devm_backlight_release(void *data) | ||
627 | { | ||
628 | backlight_put(data); | ||
629 | } | ||
630 | |||
631 | /** | ||
632 | * devm_of_find_backlight - Resource-managed of_find_backlight() | ||
633 | * @dev: Device | ||
634 | * | ||
635 | * Device managed version of of_find_backlight(). | ||
636 | * The reference on the backlight device is automatically | ||
637 | * dropped on driver detach. | ||
638 | */ | ||
639 | struct backlight_device *devm_of_find_backlight(struct device *dev) | ||
640 | { | ||
641 | struct backlight_device *bd; | ||
642 | int ret; | ||
643 | |||
644 | bd = of_find_backlight(dev); | ||
645 | if (IS_ERR_OR_NULL(bd)) | ||
646 | return bd; | ||
647 | ret = devm_add_action(dev, devm_backlight_release, bd); | ||
648 | if (ret) { | ||
649 | backlight_put(bd); | ||
650 | return ERR_PTR(ret); | ||
651 | } | ||
652 | return bd; | ||
653 | } | ||
654 | EXPORT_SYMBOL(devm_of_find_backlight); | ||
655 | |||
583 | static void __exit backlight_class_exit(void) | 656 | static void __exit backlight_class_exit(void) |
584 | { | 657 | { |
585 | class_destroy(backlight_class); | 658 | class_destroy(backlight_class); |
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index 182f83283e24..dd2a8cf7d20b 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h | |||
@@ -143,12 +143,13 @@ struct dw_hdmi_plat_data { | |||
143 | unsigned long mpixelclock); | 143 | unsigned long mpixelclock); |
144 | }; | 144 | }; |
145 | 145 | ||
146 | int dw_hdmi_probe(struct platform_device *pdev, | 146 | struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, |
147 | const struct dw_hdmi_plat_data *plat_data); | 147 | const struct dw_hdmi_plat_data *plat_data); |
148 | void dw_hdmi_remove(struct platform_device *pdev); | 148 | void dw_hdmi_remove(struct dw_hdmi *hdmi); |
149 | void dw_hdmi_unbind(struct device *dev); | 149 | void dw_hdmi_unbind(struct dw_hdmi *hdmi); |
150 | int dw_hdmi_bind(struct platform_device *pdev, struct drm_encoder *encoder, | 150 | struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev, |
151 | const struct dw_hdmi_plat_data *plat_data); | 151 | struct drm_encoder *encoder, |
152 | const struct dw_hdmi_plat_data *plat_data); | ||
152 | 153 | ||
153 | void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense); | 154 | void dw_hdmi_setup_rx_sense(struct device *dev, bool hpd, bool rx_sense); |
154 | 155 | ||
@@ -157,7 +158,18 @@ void dw_hdmi_audio_enable(struct dw_hdmi *hdmi); | |||
157 | void dw_hdmi_audio_disable(struct dw_hdmi *hdmi); | 158 | void dw_hdmi_audio_disable(struct dw_hdmi *hdmi); |
158 | 159 | ||
159 | /* PHY configuration */ | 160 | /* PHY configuration */ |
161 | void dw_hdmi_phy_i2c_set_addr(struct dw_hdmi *hdmi, u8 address); | ||
160 | void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, | 162 | void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, |
161 | unsigned char addr); | 163 | unsigned char addr); |
162 | 164 | ||
165 | void dw_hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, u8 enable); | ||
166 | void dw_hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, u8 enable); | ||
167 | void dw_hdmi_phy_reset(struct dw_hdmi *hdmi); | ||
168 | |||
169 | enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi, | ||
170 | void *data); | ||
171 | void dw_hdmi_phy_update_hpd(struct dw_hdmi *hdmi, void *data, | ||
172 | bool force, bool disabled, bool rxsense); | ||
173 | void dw_hdmi_phy_setup_hpd(struct dw_hdmi *hdmi, void *data); | ||
174 | |||
163 | #endif /* __IMX_HDMI_H__ */ | 175 | #endif /* __IMX_HDMI_H__ */ |
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 758a176e7b57..675cc3f8cf85 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h | |||
@@ -342,7 +342,11 @@ int drm_display_info_set_bus_formats(struct drm_display_info *info, | |||
342 | /** | 342 | /** |
343 | * struct drm_tv_connector_state - TV connector related states | 343 | * struct drm_tv_connector_state - TV connector related states |
344 | * @subconnector: selected subconnector | 344 | * @subconnector: selected subconnector |
345 | * @margins: left/right/top/bottom margins | 345 | * @margins: margins |
346 | * @margins.left: left margin | ||
347 | * @margins.right: right margin | ||
348 | * @margins.top: top margin | ||
349 | * @margins.bottom: bottom margin | ||
346 | * @mode: TV mode | 350 | * @mode: TV mode |
347 | * @brightness: brightness in percent | 351 | * @brightness: brightness in percent |
348 | * @contrast: contrast in percent | 352 | * @contrast: contrast in percent |
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index c239e6e24a10..4de97e94ef9d 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h | |||
@@ -329,6 +329,13 @@ | |||
329 | # define DP_DS_12BPC 2 | 329 | # define DP_DS_12BPC 2 |
330 | # define DP_DS_16BPC 3 | 330 | # define DP_DS_16BPC 3 |
331 | 331 | ||
332 | /* DP Forward error Correction Registers */ | ||
333 | #define DP_FEC_CAPABILITY 0x090 /* 1.4 */ | ||
334 | # define DP_FEC_CAPABLE (1 << 0) | ||
335 | # define DP_FEC_UNCORR_BLK_ERROR_COUNT_CAP (1 << 1) | ||
336 | # define DP_FEC_CORR_BLK_ERROR_COUNT_CAP (1 << 2) | ||
337 | # define DP_FEC_BIT_ERROR_COUNT_CAP (1 << 3) | ||
338 | |||
332 | /* link configuration */ | 339 | /* link configuration */ |
333 | #define DP_LINK_BW_SET 0x100 | 340 | #define DP_LINK_BW_SET 0x100 |
334 | # define DP_LINK_RATE_TABLE 0x00 /* eDP 1.4 */ | 341 | # define DP_LINK_RATE_TABLE 0x00 /* eDP 1.4 */ |
@@ -445,6 +452,19 @@ | |||
445 | #define DP_UPSTREAM_DEVICE_DP_PWR_NEED 0x118 /* 1.2 */ | 452 | #define DP_UPSTREAM_DEVICE_DP_PWR_NEED 0x118 /* 1.2 */ |
446 | # define DP_PWR_NOT_NEEDED (1 << 0) | 453 | # define DP_PWR_NOT_NEEDED (1 << 0) |
447 | 454 | ||
455 | #define DP_FEC_CONFIGURATION 0x120 /* 1.4 */ | ||
456 | # define DP_FEC_READY (1 << 0) | ||
457 | # define DP_FEC_ERR_COUNT_SEL_MASK (7 << 1) | ||
458 | # define DP_FEC_ERR_COUNT_DIS (0 << 1) | ||
459 | # define DP_FEC_UNCORR_BLK_ERROR_COUNT (1 << 1) | ||
460 | # define DP_FEC_CORR_BLK_ERROR_COUNT (2 << 1) | ||
461 | # define DP_FEC_BIT_ERROR_COUNT (3 << 1) | ||
462 | # define DP_FEC_LANE_SELECT_MASK (3 << 4) | ||
463 | # define DP_FEC_LANE_0_SELECT (0 << 4) | ||
464 | # define DP_FEC_LANE_1_SELECT (1 << 4) | ||
465 | # define DP_FEC_LANE_2_SELECT (2 << 4) | ||
466 | # define DP_FEC_LANE_3_SELECT (3 << 4) | ||
467 | |||
448 | #define DP_AUX_FRAME_SYNC_VALUE 0x15c /* eDP 1.4 */ | 468 | #define DP_AUX_FRAME_SYNC_VALUE 0x15c /* eDP 1.4 */ |
449 | # define DP_AUX_FRAME_SYNC_VALID (1 << 0) | 469 | # define DP_AUX_FRAME_SYNC_VALID (1 << 0) |
450 | 470 | ||
@@ -620,6 +640,16 @@ | |||
620 | #define DP_TEST_SINK 0x270 | 640 | #define DP_TEST_SINK 0x270 |
621 | # define DP_TEST_SINK_START (1 << 0) | 641 | # define DP_TEST_SINK_START (1 << 0) |
622 | 642 | ||
643 | #define DP_FEC_STATUS 0x280 /* 1.4 */ | ||
644 | # define DP_FEC_DECODE_EN_DETECTED (1 << 0) | ||
645 | # define DP_FEC_DECODE_DIS_DETECTED (1 << 1) | ||
646 | |||
647 | #define DP_FEC_ERROR_COUNT_LSB 0x0281 /* 1.4 */ | ||
648 | |||
649 | #define DP_FEC_ERROR_COUNT_MSB 0x0282 /* 1.4 */ | ||
650 | # define DP_FEC_ERROR_COUNT_MASK 0x7F | ||
651 | # define DP_FEC_ERR_COUNT_VALID (1 << 7) | ||
652 | |||
623 | #define DP_PAYLOAD_TABLE_UPDATE_STATUS 0x2c0 /* 1.2 MST */ | 653 | #define DP_PAYLOAD_TABLE_UPDATE_STATUS 0x2c0 /* 1.2 MST */ |
624 | # define DP_PAYLOAD_TABLE_UPDATED (1 << 0) | 654 | # define DP_PAYLOAD_TABLE_UPDATED (1 << 0) |
625 | # define DP_PAYLOAD_ACT_HANDLED (1 << 1) | 655 | # define DP_PAYLOAD_ACT_HANDLED (1 << 1) |
diff --git a/include/drm/drm_simple_kms_helper.h b/include/drm/drm_simple_kms_helper.h index 6d9adbb46293..d9e4c3c3f009 100644 --- a/include/drm/drm_simple_kms_helper.h +++ b/include/drm/drm_simple_kms_helper.h | |||
@@ -22,6 +22,20 @@ struct drm_simple_display_pipe; | |||
22 | */ | 22 | */ |
23 | struct drm_simple_display_pipe_funcs { | 23 | struct drm_simple_display_pipe_funcs { |
24 | /** | 24 | /** |
25 | * @mode_valid: | ||
26 | * | ||
27 | * This function is called to filter out valid modes from the | ||
28 | * suggestions suggested by the bridge or display. This optional | ||
29 | * hook is passed in when initializing the pipeline. | ||
30 | * | ||
31 | * RETURNS: | ||
32 | * | ||
33 | * drm_mode_status Enum | ||
34 | */ | ||
35 | enum drm_mode_status (*mode_valid)(struct drm_crtc *crtc, | ||
36 | const struct drm_display_mode *mode); | ||
37 | |||
38 | /** | ||
25 | * @enable: | 39 | * @enable: |
26 | * | 40 | * |
27 | * This function should be used to enable the pipeline. | 41 | * This function should be used to enable the pipeline. |
diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h index 848b463a0af5..425ad80ed2ac 100644 --- a/include/drm/drm_vblank.h +++ b/include/drm/drm_vblank.h | |||
@@ -55,8 +55,24 @@ struct drm_pending_vblank_event { | |||
55 | * @event: Actual event which will be sent to userspace. | 55 | * @event: Actual event which will be sent to userspace. |
56 | */ | 56 | */ |
57 | union { | 57 | union { |
58 | /** | ||
59 | * @event.base: DRM event base class. | ||
60 | */ | ||
58 | struct drm_event base; | 61 | struct drm_event base; |
62 | |||
63 | /** | ||
64 | * @event.vbl: | ||
65 | * | ||
66 | * Event payload for vblank events, requested through | ||
67 | * either the MODE_PAGE_FLIP or MODE_ATOMIC IOCTL. Also | ||
68 | * generated by the legacy WAIT_VBLANK IOCTL, but new userspace | ||
69 | * should use MODE_QUEUE_SEQUENCE and &event.seq instead. | ||
70 | */ | ||
59 | struct drm_event_vblank vbl; | 71 | struct drm_event_vblank vbl; |
72 | |||
73 | /** | ||
74 | * @event.seq: Event payload for the MODE_QUEUEU_SEQUENCE IOCTL. | ||
75 | */ | ||
60 | struct drm_event_crtc_sequence seq; | 76 | struct drm_event_crtc_sequence seq; |
61 | } event; | 77 | } event; |
62 | }; | 78 | }; |
diff --git a/include/drm/tinydrm/tinydrm-helpers.h b/include/drm/tinydrm/tinydrm-helpers.h index d554ded60ee9..0a4ddbc04c60 100644 --- a/include/drm/tinydrm/tinydrm-helpers.h +++ b/include/drm/tinydrm/tinydrm-helpers.h | |||
@@ -46,10 +46,6 @@ void tinydrm_xrgb8888_to_rgb565(u16 *dst, void *vaddr, | |||
46 | void tinydrm_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb, | 46 | void tinydrm_xrgb8888_to_gray8(u8 *dst, void *vaddr, struct drm_framebuffer *fb, |
47 | struct drm_clip_rect *clip); | 47 | struct drm_clip_rect *clip); |
48 | 48 | ||
49 | struct backlight_device *tinydrm_of_find_backlight(struct device *dev); | ||
50 | int tinydrm_enable_backlight(struct backlight_device *backlight); | ||
51 | int tinydrm_disable_backlight(struct backlight_device *backlight); | ||
52 | |||
53 | size_t tinydrm_spi_max_transfer_size(struct spi_device *spi, size_t max_len); | 49 | size_t tinydrm_spi_max_transfer_size(struct spi_device *spi, size_t max_len); |
54 | bool tinydrm_spi_bpw_supported(struct spi_device *spi, u8 bpw); | 50 | bool tinydrm_spi_bpw_supported(struct spi_device *spi, u8 bpw); |
55 | int tinydrm_spi_transfer(struct spi_device *spi, u32 speed_hz, | 51 | int tinydrm_spi_transfer(struct spi_device *spi, u32 speed_hz, |
diff --git a/include/linux/backlight.h b/include/linux/backlight.h index af7003548593..2baab6f3861d 100644 --- a/include/linux/backlight.h +++ b/include/linux/backlight.h | |||
@@ -130,6 +130,48 @@ static inline int backlight_update_status(struct backlight_device *bd) | |||
130 | return ret; | 130 | return ret; |
131 | } | 131 | } |
132 | 132 | ||
133 | /** | ||
134 | * backlight_enable - Enable backlight | ||
135 | * @bd: the backlight device to enable | ||
136 | */ | ||
137 | static inline int backlight_enable(struct backlight_device *bd) | ||
138 | { | ||
139 | if (!bd) | ||
140 | return 0; | ||
141 | |||
142 | bd->props.power = FB_BLANK_UNBLANK; | ||
143 | bd->props.fb_blank = FB_BLANK_UNBLANK; | ||
144 | bd->props.state &= ~BL_CORE_FBBLANK; | ||
145 | |||
146 | return backlight_update_status(bd); | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * backlight_disable - Disable backlight | ||
151 | * @bd: the backlight device to disable | ||
152 | */ | ||
153 | static inline int backlight_disable(struct backlight_device *bd) | ||
154 | { | ||
155 | if (!bd) | ||
156 | return 0; | ||
157 | |||
158 | bd->props.power = FB_BLANK_POWERDOWN; | ||
159 | bd->props.fb_blank = FB_BLANK_POWERDOWN; | ||
160 | bd->props.state |= BL_CORE_FBBLANK; | ||
161 | |||
162 | return backlight_update_status(bd); | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * backlight_put - Drop backlight reference | ||
167 | * @bd: the backlight device to put | ||
168 | */ | ||
169 | static inline void backlight_put(struct backlight_device *bd) | ||
170 | { | ||
171 | if (bd) | ||
172 | put_device(&bd->dev); | ||
173 | } | ||
174 | |||
133 | extern struct backlight_device *backlight_device_register(const char *name, | 175 | extern struct backlight_device *backlight_device_register(const char *name, |
134 | struct device *dev, void *devdata, const struct backlight_ops *ops, | 176 | struct device *dev, void *devdata, const struct backlight_ops *ops, |
135 | const struct backlight_properties *props); | 177 | const struct backlight_properties *props); |
@@ -173,4 +215,20 @@ of_find_backlight_by_node(struct device_node *node) | |||
173 | } | 215 | } |
174 | #endif | 216 | #endif |
175 | 217 | ||
218 | #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) | ||
219 | struct backlight_device *of_find_backlight(struct device *dev); | ||
220 | struct backlight_device *devm_of_find_backlight(struct device *dev); | ||
221 | #else | ||
222 | static inline struct backlight_device *of_find_backlight(struct device *dev) | ||
223 | { | ||
224 | return NULL; | ||
225 | } | ||
226 | |||
227 | static inline struct backlight_device * | ||
228 | devm_of_find_backlight(struct device *dev) | ||
229 | { | ||
230 | return NULL; | ||
231 | } | ||
232 | #endif | ||
233 | |||
176 | #endif | 234 | #endif |