1801ab9e9SSimon Glass /*
2801ab9e9SSimon Glass * Copyright (C) 2015 Google, Inc
3801ab9e9SSimon Glass * Written by Simon Glass <sjg@chromium.org>
4801ab9e9SSimon Glass *
5801ab9e9SSimon Glass * SPDX-License-Identifier: GPL-2.0+
6801ab9e9SSimon Glass */
7801ab9e9SSimon Glass
8801ab9e9SSimon Glass #include <common.h>
9801ab9e9SSimon Glass #include <dm.h>
10801ab9e9SSimon Glass #include <errno.h>
11d2bb07b7SVasily Khoruzhick #include <edid.h>
12801ab9e9SSimon Glass #include <video_bridge.h>
13801ab9e9SSimon Glass
video_bridge_set_backlight(struct udevice * dev,int percent)14801ab9e9SSimon Glass int video_bridge_set_backlight(struct udevice *dev, int percent)
15801ab9e9SSimon Glass {
16801ab9e9SSimon Glass struct video_bridge_ops *ops = video_bridge_get_ops(dev);
17801ab9e9SSimon Glass
18801ab9e9SSimon Glass if (!ops->set_backlight)
19801ab9e9SSimon Glass return -ENOSYS;
20801ab9e9SSimon Glass
21801ab9e9SSimon Glass return ops->set_backlight(dev, percent);
22801ab9e9SSimon Glass }
23801ab9e9SSimon Glass
video_bridge_attach(struct udevice * dev)24801ab9e9SSimon Glass int video_bridge_attach(struct udevice *dev)
25801ab9e9SSimon Glass {
26801ab9e9SSimon Glass struct video_bridge_ops *ops = video_bridge_get_ops(dev);
27801ab9e9SSimon Glass
28801ab9e9SSimon Glass if (!ops->attach)
29801ab9e9SSimon Glass return -ENOSYS;
30801ab9e9SSimon Glass
31801ab9e9SSimon Glass return ops->attach(dev);
32801ab9e9SSimon Glass }
33801ab9e9SSimon Glass
video_bridge_check_attached(struct udevice * dev)34801ab9e9SSimon Glass int video_bridge_check_attached(struct udevice *dev)
35801ab9e9SSimon Glass {
36801ab9e9SSimon Glass struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
37801ab9e9SSimon Glass struct video_bridge_ops *ops = video_bridge_get_ops(dev);
38801ab9e9SSimon Glass int ret;
39801ab9e9SSimon Glass
40801ab9e9SSimon Glass if (!ops->check_attached) {
41801ab9e9SSimon Glass ret = dm_gpio_get_value(&uc_priv->hotplug);
42801ab9e9SSimon Glass
43801ab9e9SSimon Glass return ret > 0 ? 0 : ret == 0 ? -ENOTCONN : ret;
44801ab9e9SSimon Glass }
45801ab9e9SSimon Glass
46801ab9e9SSimon Glass return ops->check_attached(dev);
47801ab9e9SSimon Glass }
48801ab9e9SSimon Glass
video_bridge_read_edid(struct udevice * dev,u8 * buf,int buf_size)49d2bb07b7SVasily Khoruzhick int video_bridge_read_edid(struct udevice *dev, u8 *buf, int buf_size)
50d2bb07b7SVasily Khoruzhick {
51d2bb07b7SVasily Khoruzhick struct video_bridge_ops *ops = video_bridge_get_ops(dev);
52d2bb07b7SVasily Khoruzhick
53d2bb07b7SVasily Khoruzhick if (!ops || !ops->read_edid)
54d2bb07b7SVasily Khoruzhick return -ENOSYS;
55d2bb07b7SVasily Khoruzhick return ops->read_edid(dev, buf, buf_size);
56d2bb07b7SVasily Khoruzhick }
57d2bb07b7SVasily Khoruzhick
video_bridge_get_timing(struct udevice * dev)58*75eb6fceSAlgea Cao int video_bridge_get_timing(struct udevice *dev)
59*75eb6fceSAlgea Cao {
60*75eb6fceSAlgea Cao struct video_bridge_ops *ops = video_bridge_get_ops(dev);
61*75eb6fceSAlgea Cao
62*75eb6fceSAlgea Cao if (!ops || !ops->get_timing)
63*75eb6fceSAlgea Cao return -ENOSYS;
64*75eb6fceSAlgea Cao return ops->get_timing(dev);
65*75eb6fceSAlgea Cao }
66*75eb6fceSAlgea Cao
video_bridge_pre_probe(struct udevice * dev)67801ab9e9SSimon Glass static int video_bridge_pre_probe(struct udevice *dev)
68801ab9e9SSimon Glass {
69801ab9e9SSimon Glass struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
70801ab9e9SSimon Glass int ret;
71801ab9e9SSimon Glass
72801ab9e9SSimon Glass debug("%s\n", __func__);
73801ab9e9SSimon Glass ret = gpio_request_by_name(dev, "sleep-gpios", 0,
74801ab9e9SSimon Glass &uc_priv->sleep, GPIOD_IS_OUT);
75801ab9e9SSimon Glass if (ret) {
76801ab9e9SSimon Glass debug("%s: Could not decode sleep-gpios (%d)\n", __func__, ret);
77d4bf91adSSimon Glass if (ret != -ENOENT)
78801ab9e9SSimon Glass return ret;
79801ab9e9SSimon Glass }
805eaeadaaSSimon Glass /*
815eaeadaaSSimon Glass * Drop this for now as we do not have driver model pinctrl support
825eaeadaaSSimon Glass *
835eaeadaaSSimon Glass * ret = dm_gpio_set_pull(&uc_priv->sleep, GPIO_PULL_NONE);
845eaeadaaSSimon Glass * if (ret) {
855eaeadaaSSimon Glass * debug("%s: Could not set sleep pull value\n", __func__);
865eaeadaaSSimon Glass * return ret;
875eaeadaaSSimon Glass * }
885eaeadaaSSimon Glass */
89801ab9e9SSimon Glass ret = gpio_request_by_name(dev, "reset-gpios", 0, &uc_priv->reset,
90801ab9e9SSimon Glass GPIOD_IS_OUT);
91801ab9e9SSimon Glass if (ret) {
92801ab9e9SSimon Glass debug("%s: Could not decode reset-gpios (%d)\n", __func__, ret);
93d4bf91adSSimon Glass if (ret != -ENOENT)
94801ab9e9SSimon Glass return ret;
95801ab9e9SSimon Glass }
965eaeadaaSSimon Glass /*
975eaeadaaSSimon Glass * Drop this for now as we do not have driver model pinctrl support
985eaeadaaSSimon Glass *
995eaeadaaSSimon Glass * ret = dm_gpio_set_pull(&uc_priv->reset, GPIO_PULL_NONE);
1005eaeadaaSSimon Glass * if (ret) {
1015eaeadaaSSimon Glass * debug("%s: Could not set reset pull value\n", __func__);
1025eaeadaaSSimon Glass * return ret;
1035eaeadaaSSimon Glass * }
1045eaeadaaSSimon Glass */
105801ab9e9SSimon Glass ret = gpio_request_by_name(dev, "hotplug-gpios", 0, &uc_priv->hotplug,
106801ab9e9SSimon Glass GPIOD_IS_IN);
107d4bf91adSSimon Glass if (ret) {
108801ab9e9SSimon Glass debug("%s: Could not decode hotplug (%d)\n", __func__, ret);
109d4bf91adSSimon Glass if (ret != -ENOENT)
110801ab9e9SSimon Glass return ret;
111801ab9e9SSimon Glass }
112801ab9e9SSimon Glass
113801ab9e9SSimon Glass return 0;
114801ab9e9SSimon Glass }
115801ab9e9SSimon Glass
video_bridge_set_active(struct udevice * dev,bool active)116801ab9e9SSimon Glass int video_bridge_set_active(struct udevice *dev, bool active)
117801ab9e9SSimon Glass {
118801ab9e9SSimon Glass struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
1197587ed89SVasily Khoruzhick int ret = 0;
120801ab9e9SSimon Glass
121801ab9e9SSimon Glass debug("%s: %d\n", __func__, active);
1227587ed89SVasily Khoruzhick if (uc_priv->sleep.dev) {
123801ab9e9SSimon Glass ret = dm_gpio_set_value(&uc_priv->sleep, !active);
124801ab9e9SSimon Glass if (ret)
125801ab9e9SSimon Glass return ret;
1267587ed89SVasily Khoruzhick }
1277587ed89SVasily Khoruzhick
1287587ed89SVasily Khoruzhick if (!active)
1297587ed89SVasily Khoruzhick return 0;
1307587ed89SVasily Khoruzhick
1317587ed89SVasily Khoruzhick if (uc_priv->reset.dev) {
132801ab9e9SSimon Glass ret = dm_gpio_set_value(&uc_priv->reset, true);
133801ab9e9SSimon Glass if (ret)
134801ab9e9SSimon Glass return ret;
135801ab9e9SSimon Glass udelay(10);
136801ab9e9SSimon Glass ret = dm_gpio_set_value(&uc_priv->reset, false);
137801ab9e9SSimon Glass }
138801ab9e9SSimon Glass
139801ab9e9SSimon Glass return ret;
140801ab9e9SSimon Glass }
141801ab9e9SSimon Glass
142801ab9e9SSimon Glass UCLASS_DRIVER(video_bridge) = {
143801ab9e9SSimon Glass .id = UCLASS_VIDEO_BRIDGE,
144801ab9e9SSimon Glass .name = "video_bridge",
145801ab9e9SSimon Glass .per_device_auto_alloc_size = sizeof(struct video_bridge_priv),
146801ab9e9SSimon Glass .pre_probe = video_bridge_pre_probe,
147801ab9e9SSimon Glass };
148