- 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:
Tom Rini 2021-04-11 07:40:25 -04:00
commit c6a4ee2aae
22 changed files with 372 additions and 73 deletions

View File

@ -16,6 +16,10 @@
};
};
&edp {
rockchip,panel = <&edp_panel>;
};
&i2c0 {
u-boot,dm-pre-reloc;
};

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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>;
};
};

View File

@ -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;

View File

@ -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

View File

@ -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

84
drivers/pwm/cros_ec_pwm.c Normal file
View File

@ -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),
};

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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)
*/

View File

@ -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];

View File

@ -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 = 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 },
{ }
};

View File

@ -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);
/*

View File

@ -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);
}

View File

@ -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 */

View File

@ -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
*

View File

@ -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

View File

@ -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

View File

@ -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));