blob: 2084a2e03ee830b0900b64fbd545a1bdb946dc6d [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass7cf17572015-07-02 18:16:08 -06002/*
3 * Copyright (C) 2015 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
Simon Glass7cf17572015-07-02 18:16:08 -06005 */
6
Patrick Delaunay81313352021-04-27 11:02:19 +02007#define LOG_CATEGORY UCLASS_VIDEO_BRIDGE
8
Simon Glass7cf17572015-07-02 18:16:08 -06009#include <dm.h>
10#include <errno.h>
Vasily Khoruzhick82e9a5a2017-09-20 23:29:07 -070011#include <edid.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Simon Glass7cf17572015-07-02 18:16:08 -060013#include <video_bridge.h>
Simon Glassdbd79542020-05-10 11:40:11 -060014#include <linux/delay.h>
Simon Glass7cf17572015-07-02 18:16:08 -060015
16int video_bridge_set_backlight(struct udevice *dev, int percent)
17{
18 struct video_bridge_ops *ops = video_bridge_get_ops(dev);
19
20 if (!ops->set_backlight)
21 return -ENOSYS;
22
23 return ops->set_backlight(dev, percent);
24}
25
26int video_bridge_attach(struct udevice *dev)
27{
28 struct video_bridge_ops *ops = video_bridge_get_ops(dev);
29
30 if (!ops->attach)
31 return -ENOSYS;
32
33 return ops->attach(dev);
34}
35
36int video_bridge_check_attached(struct udevice *dev)
37{
38 struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
39 struct video_bridge_ops *ops = video_bridge_get_ops(dev);
40 int ret;
41
42 if (!ops->check_attached) {
43 ret = dm_gpio_get_value(&uc_priv->hotplug);
44
45 return ret > 0 ? 0 : ret == 0 ? -ENOTCONN : ret;
46 }
47
48 return ops->check_attached(dev);
49}
50
Vasily Khoruzhick82e9a5a2017-09-20 23:29:07 -070051int video_bridge_read_edid(struct udevice *dev, u8 *buf, int buf_size)
52{
53 struct video_bridge_ops *ops = video_bridge_get_ops(dev);
54
55 if (!ops || !ops->read_edid)
56 return -ENOSYS;
57 return ops->read_edid(dev, buf, buf_size);
58}
59
Simon Glass7cf17572015-07-02 18:16:08 -060060static int video_bridge_pre_probe(struct udevice *dev)
61{
62 struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
63 int ret;
64
65 debug("%s\n", __func__);
66 ret = gpio_request_by_name(dev, "sleep-gpios", 0,
67 &uc_priv->sleep, GPIOD_IS_OUT);
68 if (ret) {
69 debug("%s: Could not decode sleep-gpios (%d)\n", __func__, ret);
Simon Glass661d5de2016-01-21 19:44:53 -070070 if (ret != -ENOENT)
71 return ret;
Simon Glass7cf17572015-07-02 18:16:08 -060072 }
Simon Glassbe72e332015-08-03 08:19:20 -060073 /*
74 * Drop this for now as we do not have driver model pinctrl support
75 *
76 * ret = dm_gpio_set_pull(&uc_priv->sleep, GPIO_PULL_NONE);
77 * if (ret) {
78 * debug("%s: Could not set sleep pull value\n", __func__);
79 * return ret;
80 * }
81 */
Simon Glass7cf17572015-07-02 18:16:08 -060082 ret = gpio_request_by_name(dev, "reset-gpios", 0, &uc_priv->reset,
83 GPIOD_IS_OUT);
84 if (ret) {
85 debug("%s: Could not decode reset-gpios (%d)\n", __func__, ret);
Simon Glass661d5de2016-01-21 19:44:53 -070086 if (ret != -ENOENT)
87 return ret;
Simon Glass7cf17572015-07-02 18:16:08 -060088 }
Simon Glassbe72e332015-08-03 08:19:20 -060089 /*
90 * Drop this for now as we do not have driver model pinctrl support
91 *
92 * ret = dm_gpio_set_pull(&uc_priv->reset, GPIO_PULL_NONE);
93 * if (ret) {
94 * debug("%s: Could not set reset pull value\n", __func__);
95 * return ret;
96 * }
97 */
Simon Glass7cf17572015-07-02 18:16:08 -060098 ret = gpio_request_by_name(dev, "hotplug-gpios", 0, &uc_priv->hotplug,
99 GPIOD_IS_IN);
Simon Glass661d5de2016-01-21 19:44:53 -0700100 if (ret) {
Simon Glass7cf17572015-07-02 18:16:08 -0600101 debug("%s: Could not decode hotplug (%d)\n", __func__, ret);
Simon Glass661d5de2016-01-21 19:44:53 -0700102 if (ret != -ENOENT)
103 return ret;
Simon Glass7cf17572015-07-02 18:16:08 -0600104 }
105
106 return 0;
107}
108
109int video_bridge_set_active(struct udevice *dev, bool active)
110{
111 struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
Vasily Khoruzhicke0b22602018-11-05 20:24:29 -0800112 int ret = 0;
Simon Glass7cf17572015-07-02 18:16:08 -0600113
114 debug("%s: %d\n", __func__, active);
Vasily Khoruzhicke0b22602018-11-05 20:24:29 -0800115 if (uc_priv->sleep.dev) {
116 ret = dm_gpio_set_value(&uc_priv->sleep, !active);
117 if (ret)
118 return ret;
119 }
120
121 if (!active)
122 return 0;
123
124 if (uc_priv->reset.dev) {
Simon Glass7cf17572015-07-02 18:16:08 -0600125 ret = dm_gpio_set_value(&uc_priv->reset, true);
126 if (ret)
127 return ret;
128 udelay(10);
129 ret = dm_gpio_set_value(&uc_priv->reset, false);
130 }
131
132 return ret;
133}
134
135UCLASS_DRIVER(video_bridge) = {
136 .id = UCLASS_VIDEO_BRIDGE,
137 .name = "video_bridge",
Simon Glass8a2b47f2020-12-03 16:55:17 -0700138 .per_device_auto = sizeof(struct video_bridge_priv),
Simon Glass7cf17572015-07-02 18:16:08 -0600139 .pre_probe = video_bridge_pre_probe,
140};