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