2 * Copyright (C) 2015 Google, Inc
3 * Written by Simon Glass <sjg@chromium.org>
5 * SPDX-License-Identifier: GPL-2.0+
12 #include <video_bridge.h>
13 #include <power/regulator.h>
15 DECLARE_GLOBAL_DATA_PTR
;
18 * Initialisation of the chip is a process of writing certain values into
19 * certain registers over i2c bus. The chip in fact responds to a range of
20 * addresses on the i2c bus, so for each written value three parameters are
21 * required: i2c address, register address and the actual value.
23 * The base address is derived from the device tree, but oddly the chip
24 * responds on several addresses with different register sets for each.
28 * ps8622_write() Write a PS8622 eDP bridge i2c register
30 * @param dev I2C device
31 * @param addr_off offset from the i2c base address for ps8622
32 * @param reg_addr register address to write
33 * @param value value to be written
34 * @return 0 on success, non-0 on failure
36 static int ps8622_write(struct udevice
*dev
, unsigned addr_off
,
37 unsigned char reg_addr
, unsigned char value
)
39 struct dm_i2c_chip
*chip
= dev_get_parent_platdata(dev
);
44 msg
.addr
= chip
->chip_addr
+ addr_off
;
50 ret
= dm_i2c_xfer(dev
, &msg
, 1);
52 debug("%s: write failed, reg=%#x, value=%#x, ret=%d\n",
53 __func__
, reg_addr
, value
, ret
);
60 static int ps8622_set_backlight(struct udevice
*dev
, int percent
)
62 int level
= percent
* 255 / 100;
64 debug("%s: level=%d\n", __func__
, level
);
65 return ps8622_write(dev
, 0x01, 0xa7, level
);
68 static int ps8622_attach(struct udevice
*dev
)
70 const uint8_t *params
;
74 debug("%s: %s\n", __func__
, dev
->name
);
75 /* set the LDO providing the 1.2V rail to the Parade bridge */
76 ret
= uclass_get_device_by_phandle(UCLASS_REGULATOR
, dev
,
77 "power-supply", ®
);
79 ret
= regulator_autoset(reg
);
80 } else if (ret
!= -ENOENT
) {
81 debug("%s: Failed to enable power: ret=%d\n", __func__
, ret
);
85 ret
= video_bridge_set_active(dev
, true);
89 params
= fdt_getprop(gd
->fdt_blob
, dev_of_offset(dev
), "parade,regs",
91 if (!params
|| len
% 3) {
92 debug("%s: missing/invalid params=%p, len=%x\n", __func__
,
97 /* need to wait 20ms after power on before doing I2C writes */
99 for (i
= 0; i
< len
; i
+= 3) {
100 ret
= ps8622_write(dev
, params
[i
+ 0], params
[i
+ 1],
109 static int ps8622_probe(struct udevice
*dev
)
111 debug("%s\n", __func__
);
112 if (device_get_uclass_id(dev
->parent
) != UCLASS_I2C
)
113 return -EPROTONOSUPPORT
;
118 struct video_bridge_ops ps8622_ops
= {
119 .attach
= ps8622_attach
,
120 .set_backlight
= ps8622_set_backlight
,
123 static const struct udevice_id ps8622_ids
[] = {
124 { .compatible
= "parade,ps8622", },
125 { .compatible
= "parade,ps8625", },
129 U_BOOT_DRIVER(parade_ps8622
) = {
130 .name
= "parade_ps8622",
131 .id
= UCLASS_VIDEO_BRIDGE
,
132 .of_match
= ps8622_ids
,
133 .probe
= ps8622_probe
,