aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-04-11 07:40:25 -0400
committerTom Rini <trini@konsulko.com>2021-04-11 07:40:25 -0400
commitc6a4ee2aaee541c12d290dd25561e771396817cc (patch)
treedcc1c02b7c2dd1b6834c29317e16eab747558da0
parent59e84da0b88e4465f15d196bba59f22c906fa50d (diff)
parent38e18d6392fca9f6809cb3079af3069efc3d181f (diff)
downloadu-boot-c6a4ee2aaee541c12d290dd25561e771396817cc.zip
u-boot-c6a4ee2aaee541c12d290dd25561e771396817cc.tar.gz
u-boot-c6a4ee2aaee541c12d290dd25561e771396817cc.tar.bz2
Merge tag 'video-2021-07-rc1' of https://source.denx.de/u-boot/custodians/u-boot-video
- rk3399 eDP support - pwm backlight without a known period_ns - add Chrome OS EC PWM driver - Kconfig SIMPLE_PANEL DM_GPIO dependency - remove mb862xx driver remnants - fix KiB format in reserve_video() debug trace - fix tegra124 sor CSTM LVDS_EN_ENABLE/DISABLE config - fix line padding calculation for 16 and 24 BPP bitmaps
-rw-r--r--arch/arm/dts/rk3399-pinebook-pro-u-boot.dtsi4
-rw-r--r--arch/arm/include/asm/arch-rockchip/edp_rk3288.h9
-rw-r--r--arch/arm/include/asm/arch-rockchip/vop_rk3288.h15
-rw-r--r--common/board_f.c2
-rw-r--r--doc/device-tree-bindings/pwm/cros-ec-pwm.txt23
-rw-r--r--drivers/misc/cros_ec.c17
-rw-r--r--drivers/pwm/Kconfig9
-rw-r--r--drivers/pwm/Makefile1
-rw-r--r--drivers/pwm/cros_ec_pwm.c84
-rw-r--r--drivers/pwm/rk_pwm.c2
-rw-r--r--drivers/pwm/sandbox_pwm.c11
-rw-r--r--drivers/video/Kconfig2
-rw-r--r--drivers/video/cfb_console.c14
-rw-r--r--drivers/video/pwm_backlight.c20
-rw-r--r--drivers/video/rockchip/rk_edp.c103
-rw-r--r--drivers/video/rockchip/rk_vop.c84
-rw-r--r--drivers/video/tegra124/sor.c4
-rw-r--r--drivers/video/video_bmp.c4
-rw-r--r--include/cros_ec.h13
-rw-r--r--include/pwm.h8
-rw-r--r--scripts/config_whitelist.txt1
-rw-r--r--test/dm/pwm.c11
22 files changed, 370 insertions, 71 deletions
diff --git a/arch/arm/dts/rk3399-pinebook-pro-u-boot.dtsi b/arch/arm/dts/rk3399-pinebook-pro-u-boot.dtsi
index 1eafb40..2d87bea 100644
--- a/arch/arm/dts/rk3399-pinebook-pro-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-pinebook-pro-u-boot.dtsi
@@ -16,6 +16,10 @@
};
};
+&edp {
+ rockchip,panel = <&edp_panel>;
+};
+
&i2c0 {
u-boot,dm-pre-reloc;
};
diff --git a/arch/arm/include/asm/arch-rockchip/edp_rk3288.h b/arch/arm/include/asm/arch-rockchip/edp_rk3288.h
index 94e5bb6..9559813 100644
--- a/arch/arm/include/asm/arch-rockchip/edp_rk3288.h
+++ b/arch/arm/include/asm/arch-rockchip/edp_rk3288.h
@@ -232,8 +232,9 @@ check_member(rk3288_edp, pll_reg_5, 0xa00);
#define PD_CH0 (0x1 << 0)
/* pll_reg_1 */
-#define REF_CLK_24M (0x1 << 1)
-#define REF_CLK_27M (0x0 << 1)
+#define REF_CLK_24M (0x1 << 0)
+#define REF_CLK_27M (0x0 << 0)
+#define REF_CLK_MASK (0x1 << 0)
/* line_map */
#define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6)
@@ -296,7 +297,9 @@ check_member(rk3288_edp, pll_reg_5, 0xa00);
/* int_ctl */
#define SOFT_INT_CTRL (0x1 << 2)
-#define INT_POL (0x1 << 0)
+#define INT_POL1 (0x1 << 1)
+#define INT_POL0 (0x1 << 0)
+#define INT_POL (INT_POL0 | INT_POL1)
/* sys_ctl_1 */
#define DET_STA (0x1 << 2)
diff --git a/arch/arm/include/asm/arch-rockchip/vop_rk3288.h b/arch/arm/include/asm/arch-rockchip/vop_rk3288.h
index 52446e9..49a7141 100644
--- a/arch/arm/include/asm/arch-rockchip/vop_rk3288.h
+++ b/arch/arm/include/asm/arch-rockchip/vop_rk3288.h
@@ -85,26 +85,13 @@ enum {
LB_RGB_1280X8 = 0x5
};
-#if defined(CONFIG_ROCKCHIP_RK3399)
enum vop_modes {
VOP_MODE_EDP = 0,
VOP_MODE_MIPI,
VOP_MODE_HDMI,
- VOP_MODE_MIPI1,
- VOP_MODE_DP,
- VOP_MODE_NONE,
-};
-#else
-enum vop_modes {
- VOP_MODE_EDP = 0,
- VOP_MODE_HDMI,
VOP_MODE_LVDS,
- VOP_MODE_MIPI,
- VOP_MODE_NONE,
- VOP_MODE_AUTO_DETECT,
- VOP_MODE_UNKNOWN,
+ VOP_MODE_DP,
};
-#endif
/* VOP_VERSION_INFO */
#define M_FPGA_VERSION (0xffff << 16)
diff --git a/common/board_f.c b/common/board_f.c
index 0cddf03..203e965 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -394,7 +394,7 @@ static int reserve_video(void)
if (ret)
return ret;
debug("Reserving %luk for video at: %08lx\n",
- (unsigned long)gd->relocaddr - addr, addr);
+ ((unsigned long)gd->relocaddr - addr) >> 10, addr);
gd->relocaddr = addr;
#elif defined(CONFIG_LCD)
# ifdef CONFIG_FB_ADDR
diff --git a/doc/device-tree-bindings/pwm/cros-ec-pwm.txt b/doc/device-tree-bindings/pwm/cros-ec-pwm.txt
new file mode 100644
index 0000000..f198d08
--- /dev/null
+++ b/doc/device-tree-bindings/pwm/cros-ec-pwm.txt
@@ -0,0 +1,23 @@
+PWM controlled by ChromeOS EC
+
+Google's ChromeOS EC PWM is a simple PWM attached to the Embedded Controller
+(EC) and controlled via a host-command interface.
+
+An EC PWM node should be only found as a sub-node of the EC node (see
+doc/device-tree-bindings/misc/cros-ec.txt).
+
+Required properties:
+- compatible: Must contain "google,cros-ec-pwm"
+- #pwm-cells: Should be 1. The cell specifies the PWM index.
+
+Example:
+ cros-ec@0 {
+ compatible = "google,cros-ec-spi";
+
+ ...
+
+ cros_ec_pwm: ec-pwm {
+ compatible = "google,cros-ec-pwm";
+ #pwm-cells = <1>;
+ };
+ };
diff --git a/drivers/misc/cros_ec.c b/drivers/misc/cros_ec.c
index ebfa7c4..7904d5c 100644
--- a/drivers/misc/cros_ec.c
+++ b/drivers/misc/cros_ec.c
@@ -1170,6 +1170,23 @@ int cros_ec_battery_cutoff(struct udevice *dev, uint8_t flags)
return 0;
}
+int cros_ec_set_pwm_duty(struct udevice *dev, uint8_t index, uint16_t duty)
+{
+ struct ec_params_pwm_set_duty p;
+ int ret;
+
+ p.duty = duty;
+ p.pwm_type = EC_PWM_TYPE_GENERIC;
+ p.index = index;
+
+ ret = ec_command(dev, EC_CMD_PWM_SET_DUTY, 0, &p, sizeof(p),
+ NULL, 0);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
int cros_ec_set_ldo(struct udevice *dev, uint8_t index, uint8_t state)
{
struct ec_params_ldo_set params;
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index ccf81ab..cf7f4c6 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -9,6 +9,15 @@ config DM_PWM
frequency/period can be controlled along with the proportion of that
time that the signal is high.
+config PWM_CROS_EC
+ bool "Enable support for the Chrome OS EC PWM"
+ depends on DM_PWM
+ help
+ This PWM is found on several Chrome OS devices and controlled by
+ the Chrome OS embedded controller. It may be used to control the
+ screen brightness and/or the keyboard backlight depending on the
+ device.
+
config PWM_EXYNOS
bool "Enable support for the Exynos PWM"
depends on DM_PWM
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 0b9d269..10d244b 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -10,6 +10,7 @@
obj-$(CONFIG_DM_PWM) += pwm-uclass.o
+obj-$(CONFIG_PWM_CROS_EC) += cros_ec_pwm.o
obj-$(CONFIG_PWM_EXYNOS) += exynos_pwm.o
obj-$(CONFIG_PWM_IMX) += pwm-imx.o pwm-imx-util.o
obj-$(CONFIG_PWM_MESON) += pwm-meson.o
diff --git a/drivers/pwm/cros_ec_pwm.c b/drivers/pwm/cros_ec_pwm.c
new file mode 100644
index 0000000..44f4105
--- /dev/null
+++ b/drivers/pwm/cros_ec_pwm.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <common.h>
+#include <cros_ec.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <pwm.h>
+
+struct cros_ec_pwm_priv {
+ bool enabled;
+ uint duty;
+};
+
+static int cros_ec_pwm_set_config(struct udevice *dev, uint channel,
+ uint period_ns, uint duty_ns)
+{
+ struct cros_ec_pwm_priv *priv = dev_get_priv(dev);
+ uint duty;
+ int ret;
+
+ debug("%s: period_ns=%u, duty_ns=%u asked\n", __func__,
+ period_ns, duty_ns);
+
+ /* No way to set the period, only a relative duty cycle */
+ duty = EC_PWM_MAX_DUTY * duty_ns / period_ns;
+ if (duty > EC_PWM_MAX_DUTY)
+ duty = EC_PWM_MAX_DUTY;
+
+ if (!priv->enabled) {
+ priv->duty = duty;
+ debug("%s: duty=%#x to-be-set\n", __func__, duty);
+ return 0;
+ }
+
+ ret = cros_ec_set_pwm_duty(dev->parent, channel, duty);
+ if (ret) {
+ debug("%s: duty=%#x failed\n", __func__, duty);
+ return ret;
+ }
+
+ priv->duty = duty;
+ debug("%s: duty=%#x set\n", __func__, duty);
+
+ return 0;
+}
+
+static int cros_ec_pwm_set_enable(struct udevice *dev, uint channel,
+ bool enable)
+{
+ struct cros_ec_pwm_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ ret = cros_ec_set_pwm_duty(dev->parent, channel,
+ enable ? priv->duty : 0);
+ if (ret) {
+ debug("%s: enable=%d failed\n", __func__, enable);
+ return ret;
+ }
+
+ priv->enabled = enable;
+ debug("%s: enable=%d (duty=%#x) set\n", __func__,
+ enable, priv->duty);
+
+ return 0;
+}
+
+static const struct pwm_ops cros_ec_pwm_ops = {
+ .set_config = cros_ec_pwm_set_config,
+ .set_enable = cros_ec_pwm_set_enable,
+};
+
+static const struct udevice_id cros_ec_pwm_ids[] = {
+ { .compatible = "google,cros-ec-pwm" },
+ { }
+};
+
+U_BOOT_DRIVER(cros_ec_pwm) = {
+ .name = "cros_ec_pwm",
+ .id = UCLASS_PWM,
+ .of_match = cros_ec_pwm_ids,
+ .ops = &cros_ec_pwm_ops,
+ .priv_auto_alloc_size = sizeof(struct cros_ec_pwm_priv),
+};
diff --git a/drivers/pwm/rk_pwm.c b/drivers/pwm/rk_pwm.c
index 9cf0980..071eb04 100644
--- a/drivers/pwm/rk_pwm.c
+++ b/drivers/pwm/rk_pwm.c
@@ -147,7 +147,7 @@ static int rk_pwm_probe(struct udevice *dev)
priv->data = (struct rockchip_pwm_data *)dev_get_driver_data(dev);
if (priv->data->supports_polarity)
- priv->conf_polarity = PWM_DUTY_POSTIVE | PWM_INACTIVE_POSTIVE;
+ priv->conf_polarity = PWM_DUTY_POSTIVE | PWM_INACTIVE_NEGATIVE;
return 0;
}
diff --git a/drivers/pwm/sandbox_pwm.c b/drivers/pwm/sandbox_pwm.c
index 318dce7..4df15f0 100644
--- a/drivers/pwm/sandbox_pwm.c
+++ b/drivers/pwm/sandbox_pwm.c
@@ -59,8 +59,15 @@ static int sandbox_pwm_set_config(struct udevice *dev, uint channel,
if (channel >= NUM_CHANNELS)
return -ENOSPC;
chan = &priv->chan[channel];
- chan->period_ns = period_ns;
- chan->duty_ns = duty_ns;
+
+ if (channel == 2) {
+ /* Pretend to have some fixed period */
+ chan->period_ns = 4096;
+ chan->duty_ns = duty_ns * 4096 / period_ns;
+ } else {
+ chan->period_ns = period_ns;
+ chan->duty_ns = duty_ns;
+ }
return 0;
}
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 63ae2ba..b69ffca 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -209,7 +209,7 @@ config PANEL
config SIMPLE_PANEL
bool "Enable simple panel support"
- depends on PANEL && BACKLIGHT
+ depends on PANEL && BACKLIGHT && DM_GPIO
default y
help
This turns on a simple panel driver that enables a compatible
diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c
index 27ff716..1f491a4 100644
--- a/drivers/video/cfb_console.c
+++ b/drivers/video/cfb_console.c
@@ -82,20 +82,6 @@
#endif
/*
- * Defines for the MB862xx driver
- */
-#ifdef CONFIG_VIDEO_MB862xx
-
-#ifdef CONFIG_VIDEO_CORALP
-#define VIDEO_FB_LITTLE_ENDIAN
-#endif
-#ifdef CONFIG_VIDEO_MB862xx_ACCEL
-#define VIDEO_HW_RECTFILL
-#define VIDEO_HW_BITBLT
-#endif
-#endif
-
-/*
* Defines for the i.MX31 driver (mx3fb.c)
*/
#if defined(CONFIG_VIDEO_MX3) || defined(CONFIG_VIDEO_IPUV3)
diff --git a/drivers/video/pwm_backlight.c b/drivers/video/pwm_backlight.c
index 9e32bc4..4c86215 100644
--- a/drivers/video/pwm_backlight.c
+++ b/drivers/video/pwm_backlight.c
@@ -62,10 +62,17 @@ static int set_pwm(struct pwm_backlight_priv *priv)
uint duty_cycle;
int ret;
- duty_cycle = priv->period_ns * (priv->cur_level - priv->min_level) /
- (priv->max_level - priv->min_level);
- ret = pwm_set_config(priv->pwm, priv->channel, priv->period_ns,
- duty_cycle);
+ if (priv->period_ns) {
+ duty_cycle = priv->period_ns * (priv->cur_level - priv->min_level) /
+ (priv->max_level - priv->min_level);
+ ret = pwm_set_config(priv->pwm, priv->channel, priv->period_ns,
+ duty_cycle);
+ } else {
+ /* PWM driver will internally scale these like the above. */
+ ret = pwm_set_config(priv->pwm, priv->channel,
+ priv->max_level - priv->min_level,
+ priv->cur_level - priv->min_level);
+ }
if (ret)
return log_ret(ret);
@@ -213,10 +220,11 @@ static int pwm_backlight_of_to_plat(struct udevice *dev)
log_debug("Cannot get PWM: ret=%d\n", ret);
return log_ret(ret);
}
- if (args.args_count < 2)
+ if (args.args_count < 1)
return log_msg_ret("Not enough arguments to pwm\n", -EINVAL);
priv->channel = args.args[0];
- priv->period_ns = args.args[1];
+ if (args.args_count > 1)
+ priv->period_ns = args.args[1];
if (args.args_count > 2)
priv->polarity = args.args[2];
diff --git a/drivers/video/rockchip/rk_edp.c b/drivers/video/rockchip/rk_edp.c
index 0be60e1..0ddf5e0 100644
--- a/drivers/video/rockchip/rk_edp.c
+++ b/drivers/video/rockchip/rk_edp.c
@@ -8,20 +8,21 @@
#include <clk.h>
#include <display.h>
#include <dm.h>
+#include <dm/device_compat.h>
#include <edid.h>
#include <log.h>
#include <malloc.h>
#include <panel.h>
#include <regmap.h>
+#include <reset.h>
#include <syscon.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/hardware.h>
#include <asm/arch-rockchip/edp_rk3288.h>
#include <asm/arch-rockchip/grf_rk3288.h>
-#include <asm/arch-rockchip/hardware.h>
-#include <dt-bindings/clock/rk3288-cru.h>
-#include <linux/delay.h>
+#include <asm/arch-rockchip/grf_rk3399.h>
#define MAX_CR_LOOP 5
#define MAX_EQ_LOOP 5
@@ -37,18 +38,42 @@ static const char * const pre_emph_names[] = {
#define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200
#define DP_PRE_EMPHASIS_MAX DP_TRAIN_PRE_EMPHASIS_9_5
+#define RK3288_GRF_SOC_CON6 0x025c
+#define RK3288_GRF_SOC_CON12 0x0274
+#define RK3399_GRF_SOC_CON20 0x6250
+#define RK3399_GRF_SOC_CON25 0x6264
+
+enum rockchip_dp_types {
+ RK3288_DP = 0,
+ RK3399_EDP
+};
+
+struct rockchip_dp_data {
+ unsigned long reg_vop_big_little;
+ unsigned long reg_vop_big_little_sel;
+ unsigned long reg_ref_clk_sel;
+ unsigned long ref_clk_sel_bit;
+ enum rockchip_dp_types chip_type;
+};
+
struct rk_edp_priv {
struct rk3288_edp *regs;
- struct rk3288_grf *grf;
+ void *grf;
struct udevice *panel;
struct link_train link_train;
u8 train_set[4];
};
-static void rk_edp_init_refclk(struct rk3288_edp *regs)
+static void rk_edp_init_refclk(struct rk3288_edp *regs, enum rockchip_dp_types chip_type)
{
writel(SEL_24M, &regs->analog_ctl_2);
- writel(REF_CLK_24M, &regs->pll_reg_1);
+ u32 reg;
+
+ reg = REF_CLK_24M;
+ if (chip_type == RK3288_DP)
+ reg ^= REF_CLK_MASK;
+ writel(reg, &regs->pll_reg_1);
+
writel(LDO_OUTPUT_V_SEL_145 | KVCO_DEFALUT | CHG_PUMP_CUR_SEL_5US |
V2L_CUR_SEL_1MA, &regs->pll_reg_2);
@@ -1029,6 +1054,9 @@ static int rk_edp_probe(struct udevice *dev)
struct display_plat *uc_plat = dev_get_uclass_plat(dev);
struct rk_edp_priv *priv = dev_get_priv(dev);
struct rk3288_edp *regs = priv->regs;
+ struct rockchip_dp_data *edp_data = (struct rockchip_dp_data *)dev_get_driver_data(dev);
+ struct reset_ctl dp_rst;
+
struct clk clk;
int ret;
@@ -1040,19 +1068,39 @@ static int rk_edp_probe(struct udevice *dev)
return ret;
}
- int vop_id = uc_plat->source_id;
- debug("%s, uc_plat=%p, vop_id=%u\n", __func__, uc_plat, vop_id);
+ ret = reset_get_by_name(dev, "dp", &dp_rst);
+ if (ret) {
+ dev_err(dev, "failed to get dp reset (ret=%d)\n", ret);
+ return ret;
+ }
- ret = clk_get_by_index(dev, 1, &clk);
- if (ret >= 0) {
- ret = clk_set_rate(&clk, 0);
- clk_free(&clk);
+ ret = reset_assert(&dp_rst);
+ if (ret) {
+ dev_err(dev, "failed to assert dp reset (ret=%d)\n", ret);
+ return ret;
}
+ udelay(20);
+
+ ret = reset_deassert(&dp_rst);
if (ret) {
- debug("%s: Failed to set EDP clock: ret=%d\n", __func__, ret);
+ dev_err(dev, "failed to deassert dp reset (ret=%d)\n", ret);
return ret;
}
+ int vop_id = uc_plat->source_id;
+ debug("%s, uc_plat=%p, vop_id=%u\n", __func__, uc_plat, vop_id);
+
+ if (edp_data->chip_type == RK3288_DP) {
+ ret = clk_get_by_index(dev, 1, &clk);
+ if (ret >= 0) {
+ ret = clk_set_rate(&clk, 0);
+ clk_free(&clk);
+ }
+ if (ret) {
+ debug("%s: Failed to set EDP clock: ret=%d\n", __func__, ret);
+ return ret;
+ }
+ }
ret = clk_get_by_index(uc_plat->src_dev, 0, &clk);
if (ret >= 0) {
ret = clk_set_rate(&clk, 192000000);
@@ -1065,15 +1113,17 @@ static int rk_edp_probe(struct udevice *dev)
}
/* grf_edp_ref_clk_sel: from internal 24MHz or 27MHz clock */
- rk_setreg(&priv->grf->soc_con12, 1 << 4);
+ rk_setreg(priv->grf + edp_data->reg_ref_clk_sel,
+ edp_data->ref_clk_sel_bit);
/* select epd signal from vop0 or vop1 */
- rk_clrsetreg(&priv->grf->soc_con6, (1 << 5),
- (vop_id == 1) ? (1 << 5) : (0 << 5));
+ rk_clrsetreg(priv->grf + edp_data->reg_vop_big_little,
+ edp_data->reg_vop_big_little_sel,
+ (vop_id == 1) ? edp_data->reg_vop_big_little_sel : 0);
rockchip_edp_wait_hpd(priv);
- rk_edp_init_refclk(regs);
+ rk_edp_init_refclk(regs, edp_data->chip_type);
rk_edp_init_interrupt(regs);
rk_edp_enable_sw_function(regs);
ret = rk_edp_init_analog_func(regs);
@@ -1089,8 +1139,25 @@ static const struct dm_display_ops dp_rockchip_ops = {
.enable = rk_edp_enable,
};
+static const struct rockchip_dp_data rk3399_edp = {
+ .reg_vop_big_little = RK3399_GRF_SOC_CON20,
+ .reg_vop_big_little_sel = BIT(5),
+ .reg_ref_clk_sel = RK3399_GRF_SOC_CON25,
+ .ref_clk_sel_bit = BIT(11),
+ .chip_type = RK3399_EDP,
+};
+
+static const struct rockchip_dp_data rk3288_dp = {
+ .reg_vop_big_little = RK3288_GRF_SOC_CON6,
+ .reg_vop_big_little_sel = BIT(5),
+ .reg_ref_clk_sel = RK3288_GRF_SOC_CON12,
+ .ref_clk_sel_bit = BIT(4),
+ .chip_type = RK3288_DP,
+};
+
static const struct udevice_id rockchip_dp_ids[] = {
- { .compatible = "rockchip,rk3288-edp" },
+ { .compatible = "rockchip,rk3288-edp", .data = (ulong)&rk3288_dp },
+ { .compatible = "rockchip,rk3399-edp", .data = (ulong)&rk3399_edp },
{ }
};
diff --git a/drivers/video/rockchip/rk_vop.c b/drivers/video/rockchip/rk_vop.c
index 145c333..fe05748 100644
--- a/drivers/video/rockchip/rk_vop.c
+++ b/drivers/video/rockchip/rk_vop.c
@@ -8,9 +8,11 @@
#include <clk.h>
#include <display.h>
#include <dm.h>
+#include <dm/device_compat.h>
#include <edid.h>
#include <log.h>
#include <regmap.h>
+#include <reset.h>
#include <syscon.h>
#include <video.h>
#include <asm/global_data.h>
@@ -21,6 +23,8 @@
#include <asm/arch-rockchip/vop_rk3288.h>
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>
+#include <efi.h>
+#include <efi_loader.h>
#include <linux/bitops.h>
#include <linux/err.h>
#include <power/regulator.h>
@@ -35,14 +39,16 @@ enum vop_pol {
DCLK_INVERT = 3
};
-static void rkvop_enable(struct rk3288_vop *regs, ulong fbbase,
+static void rkvop_enable(struct udevice *dev, struct rk3288_vop *regs, ulong fbbase,
int fb_bits_per_pixel,
- const struct display_timing *edid)
+ const struct display_timing *edid,
+ struct reset_ctl *dclk_rst)
{
u32 lb_mode;
u32 rgb_mode;
u32 hactive = edid->hactive.typ;
u32 vactive = edid->vactive.typ;
+ int ret;
writel(V_ACT_WIDTH(hactive - 1) | V_ACT_HEIGHT(vactive - 1),
&regs->win0_act_info);
@@ -90,6 +96,18 @@ static void rkvop_enable(struct rk3288_vop *regs, ulong fbbase,
writel(fbbase, &regs->win0_yrgb_mst);
writel(0x01, &regs->reg_cfg_done); /* enable reg config */
+
+ ret = reset_assert(dclk_rst);
+ if (ret) {
+ dev_warn(dev, "failed to assert dclk reset (ret=%d)\n", ret);
+ return;
+ }
+ udelay(20);
+
+ ret = reset_deassert(dclk_rst);
+ if (ret)
+ dev_warn(dev, "failed to deassert dclk reset (ret=%d)\n", ret);
+
}
static void rkvop_set_pin_polarity(struct udevice *dev,
@@ -236,12 +254,12 @@ static int rk_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
struct clk clk;
enum video_log2_bpp l2bpp;
ofnode remote;
+ const char *compat;
+ struct reset_ctl dclk_rst;
- debug("%s(%s, %lu, %s)\n", __func__,
+ debug("%s(%s, 0x%lx, %s)\n", __func__,
dev_read_name(dev), fbbase, ofnode_get_name(ep_node));
- vop_id = ofnode_read_s32_default(ep_node, "reg", -1);
- debug("vop_id=%d\n", vop_id);
ret = ofnode_read_u32(ep_node, "remote-endpoint", &remote_phandle);
if (ret)
return ret;
@@ -283,6 +301,28 @@ static int rk_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
if (disp)
break;
};
+ compat = ofnode_get_property(remote, "compatible", NULL);
+ if (!compat) {
+ debug("%s(%s): Failed to find compatible property\n",
+ __func__, dev_read_name(dev));
+ return -EINVAL;
+ }
+ if (strstr(compat, "edp")) {
+ vop_id = VOP_MODE_EDP;
+ } else if (strstr(compat, "mipi")) {
+ vop_id = VOP_MODE_MIPI;
+ } else if (strstr(compat, "hdmi")) {
+ vop_id = VOP_MODE_HDMI;
+ } else if (strstr(compat, "cdn-dp")) {
+ vop_id = VOP_MODE_DP;
+ } else if (strstr(compat, "lvds")) {
+ vop_id = VOP_MODE_LVDS;
+ } else {
+ debug("%s(%s): Failed to find vop mode for %s\n",
+ __func__, dev_read_name(dev), compat);
+ return -EINVAL;
+ }
+ debug("vop_id=%d\n", vop_id);
disp_uc_plat = dev_get_uclass_plat(disp);
debug("Found device '%s', disp_uc_priv=%p\n", disp->name, disp_uc_plat);
@@ -332,7 +372,14 @@ static int rk_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
}
rkvop_mode_set(dev, &timing, vop_id);
- rkvop_enable(regs, fbbase, 1 << l2bpp, &timing);
+
+ ret = reset_get_by_name(dev, "dclk", &dclk_rst);
+ if (ret) {
+ dev_err(dev, "failed to get dclk reset (ret=%d)\n", ret);
+ return ret;
+ }
+
+ rkvop_enable(dev, regs, fbbase, 1 << l2bpp, &timing, &dclk_rst);
ret = display_enable(disp, 1 << l2bpp, &timing);
if (ret)
@@ -369,11 +416,36 @@ int rk_vop_probe(struct udevice *dev)
struct rk_vop_priv *priv = dev_get_priv(dev);
int ret = 0;
ofnode port, node;
+ struct reset_ctl ahb_rst;
/* Before relocation we don't need to do anything */
if (!(gd->flags & GD_FLG_RELOC))
return 0;
+ ret = reset_get_by_name(dev, "ahb", &ahb_rst);
+ if (ret) {
+ dev_err(dev, "failed to get ahb reset (ret=%d)\n", ret);
+ return ret;
+ }
+
+ ret = reset_assert(&ahb_rst);
+ if (ret) {
+ dev_err(dev, "failed to assert ahb reset (ret=%d)\n", ret);
+ return ret;
+ }
+ udelay(20);
+
+ ret = reset_deassert(&ahb_rst);
+ if (ret) {
+ dev_err(dev, "failed to deassert ahb reset (ret=%d)\n", ret);
+ return ret;
+ }
+
+#if defined(CONFIG_EFI_LOADER)
+ debug("Adding to EFI map %d @ %lx\n", plat->size, plat->base);
+ efi_add_memory_map(plat->base, plat->size, EFI_RESERVED_MEMORY_TYPE);
+#endif
+
priv->regs = (struct rk3288_vop *)dev_read_addr(dev);
/*
diff --git a/drivers/video/tegra124/sor.c b/drivers/video/tegra124/sor.c
index 95976ee..ef1a2e6 100644
--- a/drivers/video/tegra124/sor.c
+++ b/drivers/video/tegra124/sor.c
@@ -671,8 +671,8 @@ static void tegra_dc_sor_config_panel(struct tegra_dc_sor_data *sor,
CSTM_ROTCLK_DEFAULT_MASK |
CSTM_LVDS_EN_ENABLE,
2 << CSTM_ROTCLK_SHIFT |
- is_lvds ? CSTM_LVDS_EN_ENABLE :
- CSTM_LVDS_EN_DISABLE);
+ (is_lvds ? CSTM_LVDS_EN_ENABLE :
+ CSTM_LVDS_EN_DISABLE));
tegra_dc_sor_config_pwm(sor, 1024, 1024);
}
diff --git a/drivers/video/video_bmp.c b/drivers/video/video_bmp.c
index 66de223..1e6f07f 100644
--- a/drivers/video/video_bmp.c
+++ b/drivers/video/video_bmp.c
@@ -328,7 +328,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
for (j = 0; j < width; j++)
fb_put_word(&fb, &bmap);
- bmap += (padded_width - width) * 2;
+ bmap += (padded_width - width);
fb -= width * 2 + priv->line_length;
}
break;
@@ -352,7 +352,7 @@ int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
}
}
fb -= priv->line_length + width * (bpix / 8);
- bmap += (padded_width - width) * 3;
+ bmap += (padded_width - width);
}
break;
#endif /* CONFIG_BMP_24BPP */
diff --git a/include/cros_ec.h b/include/cros_ec.h
index eddc23d..9396b4d 100644
--- a/include/cros_ec.h
+++ b/include/cros_ec.h
@@ -513,6 +513,19 @@ int cros_ec_efs_verify(struct udevice *dev, enum ec_flash_region region);
int cros_ec_battery_cutoff(struct udevice *dev, uint8_t flags);
/**
+ * cros_ec_set_pwm_duty() - Set duty cycle of a generic pwm
+ *
+ * Note that duty value needs to be passed to the EC as a 16 bit number
+ * for increased precision.
+ *
+ * @param dev CROS-EC device
+ * @param index Index of the pwm
+ * @param duty Desired duty cycle, in 0..EC_PWM_MAX_DUTY range.
+ * @return 0 if OK, -ve on error
+ */
+int cros_ec_set_pwm_duty(struct udevice *dev, uint8_t index, uint16_t duty);
+
+/**
* cros_ec_read_limit_power() - Check if power is limited by batter/charger
*
* Sometimes the battery is low and / or the device is connected to a charger
diff --git a/include/pwm.h b/include/pwm.h
index f995970..668551e 100644
--- a/include/pwm.h
+++ b/include/pwm.h
@@ -17,6 +17,10 @@ struct pwm_ops {
/**
* set_config() - Set the PWM configuration
*
+ * Change both the PWM device's period and it's duty period if
+ * possible. Otherwise, set an appropriate duty period that best
+ * matches the given period_ns / duty_ns ratio for the device.
+ *
* @dev: PWM device to update
* @channel: PWM channel to update
* @period_ns: PWM period in nanoseconds
@@ -51,6 +55,10 @@ struct pwm_ops {
/**
* pwm_set_config() - Set the PWM configuration
*
+ * Change both the PWM device's period and it's duty period if
+ * possible. Otherwise, set an appropriate duty period that best
+ * matches the given period_ns / duty_ns ratio for the device.
+ *
* @dev: PWM device to update
* @channel: PWM channel to update
* @period_ns: PWM period in nanoseconds
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index 6859d17..39e6416 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -3939,7 +3939,6 @@ CONFIG_VEXPRESS_EXTENDED_MEMORY_MAP
CONFIG_VEXPRESS_ORIGINAL_MEMORY_MAP
CONFIG_VIDEO_BCM2835
CONFIG_VIDEO_BMP_LOGO
-CONFIG_VIDEO_CORALP
CONFIG_VIDEO_DA8XX
CONFIG_VIDEO_FONT_4X6
CONFIG_VIDEO_LCD_I2C_BUS
diff --git a/test/dm/pwm.c b/test/dm/pwm.c
index 0de6dba..b624cf3 100644
--- a/test/dm/pwm.c
+++ b/test/dm/pwm.c
@@ -6,6 +6,7 @@
#include <common.h>
#include <dm.h>
#include <pwm.h>
+#include <asm/test.h>
#include <dm/test.h>
#include <test/test.h>
#include <test/ut.h>
@@ -14,6 +15,10 @@
static int dm_test_pwm_base(struct unit_test_state *uts)
{
struct udevice *dev;
+ uint period_ns;
+ uint duty_ns;
+ bool enable;
+ bool polarity;
ut_assertok(uclass_get_device(UCLASS_PWM, 0, &dev));
ut_assertnonnull(dev);
@@ -24,6 +29,12 @@ static int dm_test_pwm_base(struct unit_test_state *uts)
ut_asserteq(-ENOSPC, pwm_set_enable(dev, 3, true));
ut_assertok(pwm_set_invert(dev, 0, true));
+ ut_assertok(pwm_set_config(dev, 2, 100, 50));
+ ut_assertok(sandbox_pwm_get_config(dev, 2, &period_ns, &duty_ns,
+ &enable, &polarity));
+ ut_asserteq(period_ns, 4096);
+ ut_asserteq(duty_ns, 50 * 4096 / 100);
+
ut_assertok(uclass_get_device(UCLASS_PWM, 1, &dev));
ut_asserteq(-ENODEV, uclass_get_device(UCLASS_PWM, 2, &dev));