1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2015 Google, Inc
12 #include <video_bridge.h>
13 #include <asm/global_data.h>
14 #include <linux/delay.h>
15 #include <power/regulator.h>
17 DECLARE_GLOBAL_DATA_PTR;
20 * Initialisation of the chip is a process of writing certain values into
21 * certain registers over i2c bus. The chip in fact responds to a range of
22 * addresses on the i2c bus, so for each written value three parameters are
23 * required: i2c address, register address and the actual value.
25 * The base address is derived from the device tree, but oddly the chip
26 * responds on several addresses with different register sets for each.
30 * ps8622_write() Write a PS8622 eDP bridge i2c register
32 * @param dev I2C device
33 * @param addr_off offset from the i2c base address for ps8622
34 * @param reg_addr register address to write
35 * @param value value to be written
36 * Return: 0 on success, non-0 on failure
38 static int ps8622_write(struct udevice *dev, unsigned addr_off,
39 unsigned char reg_addr, unsigned char value)
41 struct dm_i2c_chip *chip = dev_get_parent_plat(dev);
46 msg.addr = chip->chip_addr + addr_off;
52 ret = dm_i2c_xfer(dev, &msg, 1);
54 debug("%s: write failed, reg=%#x, value=%#x, ret=%d\n",
55 __func__, reg_addr, value, ret);
62 static int ps8622_set_backlight(struct udevice *dev, int percent)
64 int level = percent * 255 / 100;
66 debug("%s: level=%d\n", __func__, level);
67 return ps8622_write(dev, 0x01, 0xa7, level);
70 static int ps8622_attach(struct udevice *dev)
72 const uint8_t *params;
76 debug("%s: %s\n", __func__, dev->name);
77 /* set the LDO providing the 1.2V rail to the Parade bridge */
78 ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
79 "power-supply", ®);
81 ret = regulator_autoset(reg);
82 } else if (ret != -ENOENT) {
83 debug("%s: Failed to enable power: ret=%d\n", __func__, ret);
87 ret = video_bridge_set_active(dev, true);
91 params = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "parade,regs",
93 if (!params || len % 3) {
94 debug("%s: missing/invalid params=%p, len=%x\n", __func__,
99 /* need to wait 20ms after power on before doing I2C writes */
101 for (i = 0; i < len; i += 3) {
102 ret = ps8622_write(dev, params[i + 0], params[i + 1],
111 static int ps8622_probe(struct udevice *dev)
113 debug("%s\n", __func__);
114 if (device_get_uclass_id(dev->parent) != UCLASS_I2C)
115 return -EPROTONOSUPPORT;
120 struct video_bridge_ops ps8622_ops = {
121 .attach = ps8622_attach,
122 .set_backlight = ps8622_set_backlight,
125 static const struct udevice_id ps8622_ids[] = {
126 { .compatible = "parade,ps8622", },
127 { .compatible = "parade,ps8625", },
131 U_BOOT_DRIVER(parade_ps8622) = {
132 .name = "parade_ps8622",
133 .id = UCLASS_VIDEO_BRIDGE,
134 .of_match = ps8622_ids,
135 .probe = ps8622_probe,