hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
....@@ -5,17 +5,16 @@
55 */
66
77 #include <linux/delay.h>
8
+#include <drm/drm_bridge_connector.h>
89
10
+#include "msm_kms.h"
911 #include "hdmi.h"
10
-
11
-struct hdmi_bridge {
12
- struct drm_bridge base;
13
- struct hdmi *hdmi;
14
-};
15
-#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
1612
1713 void msm_hdmi_bridge_destroy(struct drm_bridge *bridge)
1814 {
15
+ struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
16
+
17
+ msm_hdmi_hpd_disable(hdmi_bridge);
1918 }
2019
2120 static void msm_hdmi_power_on(struct drm_bridge *bridge)
....@@ -259,14 +258,76 @@
259258 msm_hdmi_audio_update(hdmi);
260259 }
261260
261
+static struct edid *msm_hdmi_bridge_get_edid(struct drm_bridge *bridge,
262
+ struct drm_connector *connector)
263
+{
264
+ struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
265
+ struct hdmi *hdmi = hdmi_bridge->hdmi;
266
+ struct edid *edid;
267
+ uint32_t hdmi_ctrl;
268
+
269
+ hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
270
+ hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
271
+
272
+ edid = drm_get_edid(connector, hdmi->i2c);
273
+
274
+ hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
275
+
276
+ hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
277
+
278
+ return edid;
279
+}
280
+
281
+static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
282
+ const struct drm_display_info *info,
283
+ const struct drm_display_mode *mode)
284
+{
285
+ struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
286
+ struct hdmi *hdmi = hdmi_bridge->hdmi;
287
+ const struct hdmi_platform_config *config = hdmi->config;
288
+ struct msm_drm_private *priv = bridge->dev->dev_private;
289
+ struct msm_kms *kms = priv->kms;
290
+ long actual, requested;
291
+
292
+ requested = 1000 * mode->clock;
293
+ actual = kms->funcs->round_pixclk(kms,
294
+ requested, hdmi_bridge->hdmi->encoder);
295
+
296
+ /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
297
+ * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
298
+ * instead):
299
+ */
300
+ if (config->pwr_clk_cnt > 0)
301
+ actual = clk_round_rate(hdmi->pwr_clks[0], actual);
302
+
303
+ DBG("requested=%ld, actual=%ld", requested, actual);
304
+
305
+ if (actual != requested)
306
+ return MODE_CLOCK_RANGE;
307
+
308
+ return 0;
309
+}
310
+
262311 static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
263312 .pre_enable = msm_hdmi_bridge_pre_enable,
264313 .enable = msm_hdmi_bridge_enable,
265314 .disable = msm_hdmi_bridge_disable,
266315 .post_disable = msm_hdmi_bridge_post_disable,
267316 .mode_set = msm_hdmi_bridge_mode_set,
317
+ .mode_valid = msm_hdmi_bridge_mode_valid,
318
+ .get_edid = msm_hdmi_bridge_get_edid,
319
+ .detect = msm_hdmi_bridge_detect,
268320 };
269321
322
+static void
323
+msm_hdmi_hotplug_work(struct work_struct *work)
324
+{
325
+ struct hdmi_bridge *hdmi_bridge =
326
+ container_of(work, struct hdmi_bridge, hpd_work);
327
+ struct drm_bridge *bridge = &hdmi_bridge->base;
328
+
329
+ drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge));
330
+}
270331
271332 /* initialize bridge */
272333 struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
....@@ -283,11 +344,17 @@
283344 }
284345
285346 hdmi_bridge->hdmi = hdmi;
347
+ INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work);
286348
287349 bridge = &hdmi_bridge->base;
288350 bridge->funcs = &msm_hdmi_bridge_funcs;
351
+ bridge->ddc = hdmi->i2c;
352
+ bridge->type = DRM_MODE_CONNECTOR_HDMIA;
353
+ bridge->ops = DRM_BRIDGE_OP_HPD |
354
+ DRM_BRIDGE_OP_DETECT |
355
+ DRM_BRIDGE_OP_EDID;
289356
290
- ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, 0);
357
+ ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
291358 if (ret)
292359 goto fail;
293360