Commit | Line | Data |
---|---|---|
caab277b | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
c8afe684 RC |
2 | /* |
3 | * Copyright (C) 2013 Red Hat | |
4 | * Author: Rob Clark <robdclark@gmail.com> | |
c8afe684 RC |
5 | */ |
6 | ||
7 | #ifndef __HDMI_CONNECTOR_H__ | |
8 | #define __HDMI_CONNECTOR_H__ | |
9 | ||
10 | #include <linux/i2c.h> | |
11 | #include <linux/clk.h> | |
12 | #include <linux/platform_device.h> | |
13 | #include <linux/regulator/consumer.h> | |
c0c0d9ee | 14 | #include <linux/hdmi.h> |
c8afe684 | 15 | |
ee68c743 BB |
16 | #include <drm/drm_bridge.h> |
17 | ||
c8afe684 RC |
18 | #include "msm_drv.h" |
19 | #include "hdmi.xml.h" | |
20 | ||
dc50f782 | 21 | #define HDMI_MAX_NUM_GPIO 6 |
c8afe684 RC |
22 | |
23 | struct hdmi_phy; | |
dada25bd | 24 | struct hdmi_platform_config; |
c8afe684 | 25 | |
dc50f782 AT |
26 | struct hdmi_gpio_data { |
27 | int num; | |
28 | bool output; | |
29 | int value; | |
30 | const char *label; | |
31 | }; | |
32 | ||
c0c0d9ee RC |
33 | struct hdmi_audio { |
34 | bool enabled; | |
35 | struct hdmi_audio_infoframe infoframe; | |
36 | int rate; | |
37 | }; | |
38 | ||
c6a57a50 | 39 | struct hdmi_hdcp_ctrl; |
40 | ||
c8afe684 RC |
41 | struct hdmi { |
42 | struct drm_device *dev; | |
43 | struct platform_device *pdev; | |
f1427016 | 44 | struct platform_device *audio_pdev; |
c8afe684 | 45 | |
dada25bd | 46 | const struct hdmi_platform_config *config; |
c8afe684 | 47 | |
c0c0d9ee RC |
48 | /* audio state: */ |
49 | struct hdmi_audio audio; | |
50 | ||
51 | /* video state: */ | |
52 | bool power_on; | |
53 | unsigned long int pixclock; | |
54 | ||
dada25bd | 55 | void __iomem *mmio; |
c6a57a50 | 56 | void __iomem *qfprom_mmio; |
57 | phys_addr_t mmio_phy_addr; | |
c8afe684 | 58 | |
447fa529 SV |
59 | struct regulator **hpd_regs; |
60 | struct regulator **pwr_regs; | |
61 | struct clk **hpd_clks; | |
62 | struct clk **pwr_clks; | |
c8afe684 RC |
63 | |
64 | struct hdmi_phy *phy; | |
e00012b2 AT |
65 | struct device *phy_dev; |
66 | ||
c8afe684 RC |
67 | struct i2c_adapter *i2c; |
68 | struct drm_connector *connector; | |
a3376e3e RC |
69 | struct drm_bridge *bridge; |
70 | ||
71 | /* the encoder we are hooked to (outside of hdmi block) */ | |
72 | struct drm_encoder *encoder; | |
c8afe684 RC |
73 | |
74 | bool hdmi_mode; /* are we in hdmi mode? */ | |
75 | ||
76 | int irq; | |
c6a57a50 | 77 | struct workqueue_struct *workq; |
78 | ||
79 | struct hdmi_hdcp_ctrl *hdcp_ctrl; | |
80 | ||
81 | /* | |
82 | * spinlock to protect registers shared by different execution | |
83 | * REG_HDMI_CTRL | |
84 | * REG_HDMI_DDC_ARBITRATION | |
85 | * REG_HDMI_HDCP_INT_CTRL | |
86 | * REG_HDMI_HPD_CTRL | |
87 | */ | |
88 | spinlock_t reg_lock; | |
c8afe684 RC |
89 | }; |
90 | ||
91 | /* platform config data (ie. from DT, or pdata) */ | |
92 | struct hdmi_platform_config { | |
dada25bd | 93 | const char *mmio_name; |
c6a57a50 | 94 | const char *qfprom_mmio_name; |
dada25bd RC |
95 | |
96 | /* regulators that need to be on for hpd: */ | |
97 | const char **hpd_reg_names; | |
98 | int hpd_reg_cnt; | |
99 | ||
100 | /* regulators that need to be on for screen pwr: */ | |
101 | const char **pwr_reg_names; | |
102 | int pwr_reg_cnt; | |
103 | ||
104 | /* clks that need to be on for hpd: */ | |
105 | const char **hpd_clk_names; | |
b77f47e7 | 106 | const long unsigned *hpd_freq; |
dada25bd RC |
107 | int hpd_clk_cnt; |
108 | ||
109 | /* clks that need to be on for screen pwr (ie pixel clk): */ | |
110 | const char **pwr_clk_names; | |
111 | int pwr_clk_cnt; | |
112 | ||
113 | /* gpio's: */ | |
dc50f782 | 114 | struct hdmi_gpio_data gpios[HDMI_MAX_NUM_GPIO]; |
c8afe684 RC |
115 | }; |
116 | ||
fcda50c8 | 117 | void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on); |
c8afe684 RC |
118 | |
119 | static inline void hdmi_write(struct hdmi *hdmi, u32 reg, u32 data) | |
120 | { | |
121 | msm_writel(data, hdmi->mmio + reg); | |
122 | } | |
123 | ||
124 | static inline u32 hdmi_read(struct hdmi *hdmi, u32 reg) | |
125 | { | |
126 | return msm_readl(hdmi->mmio + reg); | |
127 | } | |
128 | ||
c6a57a50 | 129 | static inline u32 hdmi_qfprom_read(struct hdmi *hdmi, u32 reg) |
130 | { | |
131 | return msm_readl(hdmi->qfprom_mmio + reg); | |
132 | } | |
133 | ||
c8afe684 | 134 | /* |
15b4a452 | 135 | * hdmi phy: |
c8afe684 | 136 | */ |
c8afe684 | 137 | |
15b4a452 AT |
138 | enum hdmi_phy_type { |
139 | MSM_HDMI_PHY_8x60, | |
140 | MSM_HDMI_PHY_8960, | |
141 | MSM_HDMI_PHY_8x74, | |
e17afdce | 142 | MSM_HDMI_PHY_8996, |
15b4a452 AT |
143 | MSM_HDMI_PHY_MAX, |
144 | }; | |
145 | ||
146 | struct hdmi_phy_cfg { | |
147 | enum hdmi_phy_type type; | |
148 | void (*powerup)(struct hdmi_phy *phy, unsigned long int pixclock); | |
149 | void (*powerdown)(struct hdmi_phy *phy); | |
150 | const char * const *reg_names; | |
151 | int num_regs; | |
152 | const char * const *clk_names; | |
153 | int num_clks; | |
154 | }; | |
155 | ||
fcda50c8 AB |
156 | extern const struct hdmi_phy_cfg msm_hdmi_phy_8x60_cfg; |
157 | extern const struct hdmi_phy_cfg msm_hdmi_phy_8960_cfg; | |
158 | extern const struct hdmi_phy_cfg msm_hdmi_phy_8x74_cfg; | |
159 | extern const struct hdmi_phy_cfg msm_hdmi_phy_8996_cfg; | |
15b4a452 | 160 | |
c8afe684 | 161 | struct hdmi_phy { |
15b4a452 AT |
162 | struct platform_device *pdev; |
163 | void __iomem *mmio; | |
164 | struct hdmi_phy_cfg *cfg; | |
c8afe684 | 165 | const struct hdmi_phy_funcs *funcs; |
15b4a452 AT |
166 | struct regulator **regs; |
167 | struct clk **clks; | |
c8afe684 RC |
168 | }; |
169 | ||
15b4a452 AT |
170 | static inline void hdmi_phy_write(struct hdmi_phy *phy, u32 reg, u32 data) |
171 | { | |
172 | msm_writel(data, phy->mmio + reg); | |
173 | } | |
174 | ||
175 | static inline u32 hdmi_phy_read(struct hdmi_phy *phy, u32 reg) | |
176 | { | |
177 | return msm_readl(phy->mmio + reg); | |
178 | } | |
179 | ||
fcda50c8 AB |
180 | int msm_hdmi_phy_resource_enable(struct hdmi_phy *phy); |
181 | void msm_hdmi_phy_resource_disable(struct hdmi_phy *phy); | |
182 | void msm_hdmi_phy_powerup(struct hdmi_phy *phy, unsigned long int pixclock); | |
183 | void msm_hdmi_phy_powerdown(struct hdmi_phy *phy); | |
184 | void __init msm_hdmi_phy_driver_register(void); | |
185 | void __exit msm_hdmi_phy_driver_unregister(void); | |
15b4a452 | 186 | |
ea184891 | 187 | #ifdef CONFIG_COMMON_CLK |
fcda50c8 AB |
188 | int msm_hdmi_pll_8960_init(struct platform_device *pdev); |
189 | int msm_hdmi_pll_8996_init(struct platform_device *pdev); | |
ea184891 | 190 | #else |
0a69509f | 191 | static inline int msm_hdmi_pll_8960_init(struct platform_device *pdev) |
ea184891 AT |
192 | { |
193 | return -ENODEV; | |
194 | } | |
e17afdce | 195 | |
fcda50c8 | 196 | static inline int msm_hdmi_pll_8996_init(struct platform_device *pdev) |
e17afdce AT |
197 | { |
198 | return -ENODEV; | |
199 | } | |
ea184891 AT |
200 | #endif |
201 | ||
c0c0d9ee RC |
202 | /* |
203 | * audio: | |
204 | */ | |
f1427016 SK |
205 | /* Supported HDMI Audio channels and rates */ |
206 | #define MSM_HDMI_AUDIO_CHANNEL_2 0 | |
207 | #define MSM_HDMI_AUDIO_CHANNEL_4 1 | |
208 | #define MSM_HDMI_AUDIO_CHANNEL_6 2 | |
209 | #define MSM_HDMI_AUDIO_CHANNEL_8 3 | |
210 | ||
211 | #define HDMI_SAMPLE_RATE_32KHZ 0 | |
212 | #define HDMI_SAMPLE_RATE_44_1KHZ 1 | |
213 | #define HDMI_SAMPLE_RATE_48KHZ 2 | |
214 | #define HDMI_SAMPLE_RATE_88_2KHZ 3 | |
215 | #define HDMI_SAMPLE_RATE_96KHZ 4 | |
216 | #define HDMI_SAMPLE_RATE_176_4KHZ 5 | |
217 | #define HDMI_SAMPLE_RATE_192KHZ 6 | |
c0c0d9ee | 218 | |
fcda50c8 AB |
219 | int msm_hdmi_audio_update(struct hdmi *hdmi); |
220 | int msm_hdmi_audio_info_setup(struct hdmi *hdmi, bool enabled, | |
c0c0d9ee RC |
221 | uint32_t num_of_channels, uint32_t channel_allocation, |
222 | uint32_t level_shift, bool down_mix); | |
fcda50c8 | 223 | void msm_hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate); |
c0c0d9ee RC |
224 | |
225 | ||
a3376e3e RC |
226 | /* |
227 | * hdmi bridge: | |
228 | */ | |
229 | ||
fcda50c8 AB |
230 | struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi); |
231 | void msm_hdmi_bridge_destroy(struct drm_bridge *bridge); | |
a3376e3e | 232 | |
c8afe684 RC |
233 | /* |
234 | * hdmi connector: | |
235 | */ | |
236 | ||
fcda50c8 AB |
237 | void msm_hdmi_connector_irq(struct drm_connector *connector); |
238 | struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi); | |
ee445635 | 239 | int msm_hdmi_hpd_enable(struct drm_connector *connector); |
c8afe684 RC |
240 | |
241 | /* | |
242 | * i2c adapter for ddc: | |
243 | */ | |
244 | ||
fcda50c8 AB |
245 | void msm_hdmi_i2c_irq(struct i2c_adapter *i2c); |
246 | void msm_hdmi_i2c_destroy(struct i2c_adapter *i2c); | |
247 | struct i2c_adapter *msm_hdmi_i2c_init(struct hdmi *hdmi); | |
c8afe684 | 248 | |
c6a57a50 | 249 | /* |
250 | * hdcp | |
251 | */ | |
feb46f02 | 252 | #ifdef CONFIG_DRM_MSM_HDMI_HDCP |
fcda50c8 AB |
253 | struct hdmi_hdcp_ctrl *msm_hdmi_hdcp_init(struct hdmi *hdmi); |
254 | void msm_hdmi_hdcp_destroy(struct hdmi *hdmi); | |
255 | void msm_hdmi_hdcp_on(struct hdmi_hdcp_ctrl *hdcp_ctrl); | |
256 | void msm_hdmi_hdcp_off(struct hdmi_hdcp_ctrl *hdcp_ctrl); | |
257 | void msm_hdmi_hdcp_irq(struct hdmi_hdcp_ctrl *hdcp_ctrl); | |
feb46f02 RC |
258 | #else |
259 | static inline struct hdmi_hdcp_ctrl *msm_hdmi_hdcp_init(struct hdmi *hdmi) | |
260 | { | |
261 | return ERR_PTR(-ENXIO); | |
262 | } | |
263 | static inline void msm_hdmi_hdcp_destroy(struct hdmi *hdmi) {} | |
264 | static inline void msm_hdmi_hdcp_on(struct hdmi_hdcp_ctrl *hdcp_ctrl) {} | |
265 | static inline void msm_hdmi_hdcp_off(struct hdmi_hdcp_ctrl *hdcp_ctrl) {} | |
266 | static inline void msm_hdmi_hdcp_irq(struct hdmi_hdcp_ctrl *hdcp_ctrl) {} | |
267 | #endif | |
c6a57a50 | 268 | |
c8afe684 | 269 | #endif /* __HDMI_CONNECTOR_H__ */ |