- 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 -----BEGIN PGP SIGNATURE----- iGwEABECACwWIQSC4hxrSoIUVfFO0kRM6ATMmsalXAUCYHIVZQ4cYWd1c3RAZGVu eC5kZQAKCRBM6ATMmsalXGGUAJ43opdvM3K/Sl2jJlJedhqlHkKx4ACeOvg4BmUU tkZ6sxzf8lAS++xi0P0= =rExe -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
c6a4ee2aae
|
@ -16,6 +16,10 @@
|
|||
};
|
||||
};
|
||||
|
||||
&edp {
|
||||
rockchip,panel = <&edp_panel>;
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
};
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -81,20 +81,6 @@
|
|||
#define VIDEO_FB_16BPP_WORD_SWAP
|
||||
#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)
|
||||
*/
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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, ®s->analog_ctl_2);
|
||||
writel(REF_CLK_24M, ®s->pll_reg_1);
|
||||
u32 reg;
|
||||
|
||||
reg = REF_CLK_24M;
|
||||
if (chip_type == RK3288_DP)
|
||||
reg ^= REF_CLK_MASK;
|
||||
writel(reg, ®s->pll_reg_1);
|
||||
|
||||
|
||||
writel(LDO_OUTPUT_V_SEL_145 | KVCO_DEFALUT | CHG_PUMP_CUR_SEL_5US |
|
||||
V2L_CUR_SEL_1MA, ®s->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 = clk_get_by_index(dev, 1, &clk);
|
||||
if (ret >= 0) {
|
||||
ret = clk_set_rate(&clk, 0);
|
||||
clk_free(&clk);
|
||||
}
|
||||
ret = reset_get_by_name(dev, "dp", &dp_rst);
|
||||
if (ret) {
|
||||
debug("%s: Failed to set EDP clock: ret=%d\n", __func__, ret);
|
||||
dev_err(dev, "failed to get dp reset (ret=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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) {
|
||||
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 },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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),
|
||||
®s->win0_act_info);
|
||||
|
@ -90,6 +96,18 @@ static void rkvop_enable(struct rk3288_vop *regs, ulong fbbase,
|
|||
|
||||
writel(fbbase, ®s->win0_yrgb_mst);
|
||||
writel(0x01, ®s->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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -512,6 +512,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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
Loading…
Reference in New Issue