blob: 599c2cd44883477cc3cac58d0b4890e7c3c0329b [file] [log] [blame]
Nico Huber83693c82016-10-08 22:17:55 +02001--
Nico Huber3be61d42017-01-09 13:58:18 +01002-- Copyright (C) 2016-2017 secunet Security Networks AG
Nico Huber83693c82016-10-08 22:17:55 +02003--
4-- This program is free software; you can redistribute it and/or modify
5-- it under the terms of the GNU General Public License as published by
Nico Huber125a29e2016-10-18 00:23:54 +02006-- the Free Software Foundation; either version 2 of the License, or
7-- (at your option) any later version.
Nico Huber83693c82016-10-08 22:17:55 +02008--
9-- This program is distributed in the hope that it will be useful,
10-- but WITHOUT ANY WARRANTY; without even the implied warranty of
11-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12-- GNU General Public License for more details.
13--
14
15with HW.GFX.GMA.Config;
16with HW.GFX.GMA.Registers;
Nico Huber3be61d42017-01-09 13:58:18 +010017with HW.GFX.GMA.Config_Helpers;
Tim Wawrzynczak605660b2022-06-08 12:48:19 -060018with HW.GFX.GMA.PCH.HDMI;
Nico Huber83693c82016-10-08 22:17:55 +020019
20package body HW.GFX.GMA.Port_Detect
21is
22
Nico Huber83693c82016-10-08 22:17:55 +020023 DP_PORT_DETECTED : constant := 1 * 2 ** 2;
24 PCH_DIGI_PORT_DETECTED : constant := 1 * 2 ** 2;
25 PCH_LVDS_PORT_DETECTED : constant := 1 * 2 ** 1;
26
27 SHOTPLUG_CTL_DETECT_MASK : constant := 16#0003_0303#;
28
Tim Wawrzynczak605660b2022-06-08 12:48:19 -060029 type PCH_Digital_Port_Value is array (PCH.HDMI.IRL_PCH_HDMI_Port) of Word32;
Nico Huber83693c82016-10-08 22:17:55 +020030 SHOTPLUG_CTL_HPD_INPUT_ENABLE : constant PCH_Digital_Port_Value :=
31 (PCH_HDMI_B => 1 * 2 ** 4,
32 PCH_HDMI_C => 1 * 2 ** 12,
33 PCH_HDMI_D => 1 * 2 ** 20);
34 SHOTPLUG_CTL_SHORT_PULSE_MASK : constant PCH_Digital_Port_Value :=
35 (PCH_HDMI_B => 3 * 2 ** 2,
36 PCH_HDMI_C => 3 * 2 ** 10,
37 PCH_HDMI_D => 3 * 2 ** 18);
38 SHOTPLUG_CTL_HPD_STATUS : constant PCH_Digital_Port_Value :=
39 (PCH_HDMI_B => 3 * 2 ** 0,
40 PCH_HDMI_C => 3 * 2 ** 8,
41 PCH_HDMI_D => 3 * 2 ** 16);
42 SHOTPLUG_CTL_LONG_DETECT : constant PCH_Digital_Port_Value :=
43 (PCH_HDMI_B => 1 * 2 ** 1,
44 PCH_HDMI_C => 1 * 2 ** 9,
45 PCH_HDMI_D => 1 * 2 ** 17);
46
Tim Wawrzynczak605660b2022-06-08 12:48:19 -060047 type PCH_Digital_Regs is array (PCH.HDMI.IRL_PCH_HDMI_Port) of Registers.Registers_Index;
Nico Huber83693c82016-10-08 22:17:55 +020048 PCH_HDMI : constant PCH_Digital_Regs :=
49 (PCH_HDMI_B => Registers.PCH_HDMIB,
50 PCH_HDMI_C => Registers.PCH_HDMIC,
51 PCH_HDMI_D => Registers.PCH_HDMID);
52 PCH_DP : constant PCH_Digital_Regs :=
53 (PCH_HDMI_B => Registers.PCH_DP_B,
54 PCH_HDMI_C => Registers.PCH_DP_C,
55 PCH_HDMI_D => Registers.PCH_DP_D);
56
57 procedure Initialize
58 is
Nico Huber8beafd72020-01-07 14:59:44 +010059 LVDS_Detected,
60 eDP_Detected,
Nico Huber83693c82016-10-08 22:17:55 +020061 HDMI_Detected,
62 DP_Detected : Boolean;
63
Tim Wawrzynczak605660b2022-06-08 12:48:19 -060064 type PCH_Port_To_GMA_Port is array (PCH.HDMI.IRL_PCH_HDMI_Port) of Port_Type;
Nico Huber83693c82016-10-08 22:17:55 +020065 To_Digital_Port : constant PCH_Port_To_GMA_Port :=
Nico Huber0d454cd2016-11-21 13:33:43 +010066 (PCH_HDMI_B => HDMI1,
67 PCH_HDMI_C => HDMI2,
68 PCH_HDMI_D => HDMI3);
Nico Huber83693c82016-10-08 22:17:55 +020069 To_DP_Port : constant PCH_Port_To_GMA_Port :=
70 (PCH_HDMI_B => DP1,
71 PCH_HDMI_C => DP2,
72 PCH_HDMI_D => DP3);
73 begin
Nico Huber318bca12018-06-09 19:22:52 +020074 Config.Valid_Port (Analog) := True;
75
Nico Huber8beafd72020-01-07 14:59:44 +010076 -- PCH_LVDS
77 Registers.Is_Set_Mask
78 (Register => Registers.PCH_LVDS,
79 Mask => PCH_LVDS_PORT_DETECTED,
80 Result => LVDS_Detected);
81 Config.Valid_Port (LVDS) := LVDS_Detected;
82
83 -- eDP
84 Registers.Is_Set_Mask
85 (Register => Registers.DP_CTL_A,
86 Mask => DP_PORT_DETECTED,
87 Result => eDP_Detected);
88 Config.Valid_Port (eDP) := eDP_Detected;
Nico Huber83693c82016-10-08 22:17:55 +020089
90 -- PCH_HDMI_[BCD], PCH_DP_[BCD] share hotplug registers
Tim Wawrzynczak605660b2022-06-08 12:48:19 -060091 for PCH_Port in PCH.HDMI.IRL_PCH_HDMI_Port loop
Nico Huber83693c82016-10-08 22:17:55 +020092 Registers.Is_Set_Mask
93 (Register => PCH_HDMI (PCH_Port),
94 Mask => PCH_DIGI_PORT_DETECTED,
95 Result => HDMI_Detected);
96 Config.Valid_Port (To_Digital_Port (PCH_Port)) := HDMI_Detected;
97
98 Registers.Is_Set_Mask
99 (Register => PCH_DP (PCH_Port),
100 Mask => PCH_DIGI_PORT_DETECTED,
101 Result => DP_Detected);
102 Config.Valid_Port (To_DP_Port (PCH_Port)) := DP_Detected;
103
104 if HDMI_Detected or DP_Detected then
105 Registers.Unset_And_Set_Mask
106 (Register => Registers.SHOTPLUG_CTL,
107 Mask_Unset => SHOTPLUG_CTL_DETECT_MASK or
108 SHOTPLUG_CTL_SHORT_PULSE_MASK (PCH_Port),
109 Mask_Set => SHOTPLUG_CTL_HPD_INPUT_ENABLE (PCH_Port) or
110 SHOTPLUG_CTL_HPD_STATUS (PCH_Port)); -- clear
111 else
112 Registers.Unset_Mask
113 (Register => Registers.SHOTPLUG_CTL,
114 Mask => SHOTPLUG_CTL_DETECT_MASK or
115 SHOTPLUG_CTL_HPD_INPUT_ENABLE (PCH_Port));
116 end if;
117 end loop;
118 end Initialize;
119
Nico Huber3be61d42017-01-09 13:58:18 +0100120 procedure Hotplug_Detect (Port : in Active_Port_Type; Detected : out Boolean)
Nico Huber83693c82016-10-08 22:17:55 +0200121 is
122 Ctl32 : Word32;
123 PCH_Port : constant GMA.PCH_Port :=
Nico Huber3be61d42017-01-09 13:58:18 +0100124 (case Port is
125 when DP1 => PCH_HDMI_B,
126 when DP2 => PCH_HDMI_C,
127 when DP3 => PCH_HDMI_D,
128 when others => Config_Helpers.To_PCH_Port (Port));
Nico Huber83693c82016-10-08 22:17:55 +0200129 begin
Nico Huber8fb0f312017-01-18 14:35:45 +0100130 if PCH_Port in PCH_HDMI_B .. PCH_HDMI_D then
131 Registers.Read (Registers.SHOTPLUG_CTL, Ctl32, Verbose => False);
132 Detected := (Ctl32 and SHOTPLUG_CTL_LONG_DETECT (PCH_Port)) /= 0;
Nico Huber83693c82016-10-08 22:17:55 +0200133
Nico Huber8fb0f312017-01-18 14:35:45 +0100134 if (Ctl32 and SHOTPLUG_CTL_HPD_STATUS (PCH_Port)) /= 0 then
135 Registers.Unset_And_Set_Mask
136 (Register => Registers.SHOTPLUG_CTL,
137 Mask_Unset => SHOTPLUG_CTL_DETECT_MASK,
138 Mask_Set => SHOTPLUG_CTL_HPD_STATUS (PCH_Port));
139 end if;
140 else
141 Detected := False;
142 end if;
Nico Huber83693c82016-10-08 22:17:55 +0200143 end Hotplug_Detect;
144
Nico Huber4798c662017-01-11 12:44:48 +0100145 procedure Clear_Hotplug_Detect (Port : Active_Port_Type)
146 is
147 Ignored_HPD : Boolean;
148 begin
149 pragma Warnings (GNATprove, Off, "unused assignment to ""Ignored_HPD""",
150 Reason => "We want to clear pending events only");
151 Port_Detect.Hotplug_Detect (Port, Ignored_HPD);
152 pragma Warnings (GNATprove, On, "unused assignment to ""Ignored_HPD""");
153 end Clear_Hotplug_Detect;
154
Nico Huber83693c82016-10-08 22:17:55 +0200155end HW.GFX.GMA.Port_Detect;