common: Drop linux/delay.h from common header
[oweals/u-boot.git] / drivers / video / bridge / ps862x.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2015 Google, Inc
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <errno.h>
10 #include <i2c.h>
11 #include <log.h>
12 #include <video_bridge.h>
13 #include <linux/delay.h>
14 #include <power/regulator.h>
15
16 DECLARE_GLOBAL_DATA_PTR;
17
18 /*
19  * Initialisation of the chip is a process of writing certain values into
20  * certain registers over i2c bus. The chip in fact responds to a range of
21  * addresses on the i2c bus, so for each written value three parameters are
22  * required: i2c address, register address and the actual value.
23  *
24  * The base address is derived from the device tree, but oddly the chip
25  * responds on several addresses with different register sets for each.
26  */
27
28 /**
29  * ps8622_write() Write a PS8622 eDP bridge i2c register
30  *
31  * @param dev           I2C device
32  * @param addr_off      offset from the i2c base address for ps8622
33  * @param reg_addr      register address to write
34  * @param value         value to be written
35  * @return 0 on success, non-0 on failure
36  */
37 static int ps8622_write(struct udevice *dev, unsigned addr_off,
38                         unsigned char reg_addr, unsigned char value)
39 {
40         struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
41         uint8_t buf[2];
42         struct i2c_msg msg;
43         int ret;
44
45         msg.addr = chip->chip_addr + addr_off;
46         msg.flags = 0;
47         buf[0] = reg_addr;
48         buf[1] = value;
49         msg.buf = buf;
50         msg.len = 2;
51         ret = dm_i2c_xfer(dev, &msg, 1);
52         if (ret) {
53                 debug("%s: write failed, reg=%#x, value=%#x, ret=%d\n",
54                       __func__, reg_addr, value, ret);
55                 return ret;
56         }
57
58         return 0;
59 }
60
61 static int ps8622_set_backlight(struct udevice *dev, int percent)
62 {
63         int level = percent * 255 / 100;
64
65         debug("%s: level=%d\n", __func__, level);
66         return ps8622_write(dev, 0x01, 0xa7, level);
67 }
68
69 static int ps8622_attach(struct udevice *dev)
70 {
71         const uint8_t *params;
72         struct udevice *reg;
73         int ret, i, len;
74
75         debug("%s: %s\n", __func__, dev->name);
76         /* set the LDO providing the 1.2V rail to the Parade bridge */
77         ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
78                                            "power-supply", &reg);
79         if (!ret) {
80                 ret = regulator_autoset(reg);
81         } else if (ret != -ENOENT) {
82                 debug("%s: Failed to enable power: ret=%d\n", __func__, ret);
83                 return ret;
84         }
85
86         ret = video_bridge_set_active(dev, true);
87         if (ret)
88                 return ret;
89
90         params = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "parade,regs",
91                              &len);
92         if (!params || len % 3) {
93                 debug("%s: missing/invalid params=%p, len=%x\n", __func__,
94                       params, len);
95                 return -EINVAL;
96         }
97
98         /* need to wait 20ms after power on before doing I2C writes */
99         mdelay(20);
100         for (i = 0; i < len; i += 3) {
101                 ret = ps8622_write(dev, params[i + 0], params[i + 1],
102                                    params[i + 2]);
103                 if (ret)
104                         return ret;
105         }
106
107         return 0;
108 }
109
110 static int ps8622_probe(struct udevice *dev)
111 {
112         debug("%s\n", __func__);
113         if (device_get_uclass_id(dev->parent) != UCLASS_I2C)
114                 return -EPROTONOSUPPORT;
115
116         return 0;
117 }
118
119 struct video_bridge_ops ps8622_ops = {
120         .attach = ps8622_attach,
121         .set_backlight = ps8622_set_backlight,
122 };
123
124 static const struct udevice_id ps8622_ids[] = {
125         { .compatible = "parade,ps8622", },
126         { .compatible = "parade,ps8625", },
127         { }
128 };
129
130 U_BOOT_DRIVER(parade_ps8622) = {
131         .name   = "parade_ps8622",
132         .id     = UCLASS_VIDEO_BRIDGE,
133         .of_match = ps8622_ids,
134         .probe  = ps8622_probe,
135         .ops    = &ps8622_ops,
136 };