GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2015 Google, Inc
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <i2c.h>
|
||||
#include <video_bridge.h>
|
||||
#include <power/regulator.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/*
|
||||
* Initialisation of the chip is a process of writing certain values into
|
||||
* certain registers over i2c bus. The chip in fact responds to a range of
|
||||
* addresses on the i2c bus, so for each written value three parameters are
|
||||
* required: i2c address, register address and the actual value.
|
||||
*
|
||||
* The base address is derived from the device tree, but oddly the chip
|
||||
* responds on several addresses with different register sets for each.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ps8622_write() Write a PS8622 eDP bridge i2c register
|
||||
*
|
||||
* @param dev I2C device
|
||||
* @param addr_off offset from the i2c base address for ps8622
|
||||
* @param reg_addr register address to write
|
||||
* @param value value to be written
|
||||
* @return 0 on success, non-0 on failure
|
||||
*/
|
||||
static int ps8622_write(struct udevice *dev, unsigned addr_off,
|
||||
unsigned char reg_addr, unsigned char value)
|
||||
{
|
||||
struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
|
||||
uint8_t buf[2];
|
||||
struct i2c_msg msg;
|
||||
int ret;
|
||||
|
||||
msg.addr = chip->chip_addr + addr_off;
|
||||
msg.flags = 0;
|
||||
buf[0] = reg_addr;
|
||||
buf[1] = value;
|
||||
msg.buf = buf;
|
||||
msg.len = 2;
|
||||
ret = dm_i2c_xfer(dev, &msg, 1);
|
||||
if (ret) {
|
||||
debug("%s: write failed, reg=%#x, value=%#x, ret=%d\n",
|
||||
__func__, reg_addr, value, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ps8622_set_backlight(struct udevice *dev, int percent)
|
||||
{
|
||||
int level = percent * 255 / 100;
|
||||
|
||||
debug("%s: level=%d\n", __func__, level);
|
||||
return ps8622_write(dev, 0x01, 0xa7, level);
|
||||
}
|
||||
|
||||
static int ps8622_attach(struct udevice *dev)
|
||||
{
|
||||
const uint8_t *params;
|
||||
struct udevice *reg;
|
||||
int ret, i, len;
|
||||
|
||||
debug("%s: %s\n", __func__, dev->name);
|
||||
/* set the LDO providing the 1.2V rail to the Parade bridge */
|
||||
ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
|
||||
"power-supply", ®);
|
||||
if (!ret) {
|
||||
ret = regulator_autoset(reg);
|
||||
} else if (ret != -ENOENT) {
|
||||
debug("%s: Failed to enable power: ret=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = video_bridge_set_active(dev, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
params = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "parade,regs",
|
||||
&len);
|
||||
if (!params || len % 3) {
|
||||
debug("%s: missing/invalid params=%p, len=%x\n", __func__,
|
||||
params, len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* need to wait 20ms after power on before doing I2C writes */
|
||||
mdelay(20);
|
||||
for (i = 0; i < len; i += 3) {
|
||||
ret = ps8622_write(dev, params[i + 0], params[i + 1],
|
||||
params[i + 2]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ps8622_probe(struct udevice *dev)
|
||||
{
|
||||
debug("%s\n", __func__);
|
||||
if (device_get_uclass_id(dev->parent) != UCLASS_I2C)
|
||||
return -EPROTONOSUPPORT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct video_bridge_ops ps8622_ops = {
|
||||
.attach = ps8622_attach,
|
||||
.set_backlight = ps8622_set_backlight,
|
||||
};
|
||||
|
||||
static const struct udevice_id ps8622_ids[] = {
|
||||
{ .compatible = "parade,ps8622", },
|
||||
{ .compatible = "parade,ps8625", },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(parade_ps8622) = {
|
||||
.name = "parade_ps8622",
|
||||
.id = UCLASS_VIDEO_BRIDGE,
|
||||
.of_match = ps8622_ids,
|
||||
.probe = ps8622_probe,
|
||||
.ops = &ps8622_ops,
|
||||
};
|
||||
Reference in New Issue
Block a user