drm-misc-next for 4.17:
UAPI Changes: plane: Add color encoding/range properties (Jyri) nouveau: Replace iturbt_709 property with color_encoding property (Ville) Core Changes: atomic: Move plane clipping into plane check helper (Ville) property: Multiple new property checks/verification (Ville) Driver Changes: rockchip: Fixes & improvements for rk3399/chromebook plus (various) sun4i: Add H3/H5 HDMI support (Jernej) i915: Add support for limited/full-range ycbcr toggling (Ville) pl111: Add bandwidth checking/limiting (Linus) Cc: Jernej Skrabec <jernej.skrabec@siol.net> Cc: Jyri Sarha <jsarha@ti.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Linus Walleij <linus.walleij@linaro.org> -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEfxcpfMSgdnQMs+QqlvcN/ahKBwoFAlqiy/cACgkQlvcN/ahK BwpkyQgAjqswNsnUP62lEow2MXoxDYAhyIh4PGR/fIp1/+pVm+UOOSMKJyQCVkPb 6M4svzPXdawcPrIBFzfb17N73PqRw4S768N2NgiSbDEDdIW6VtzE+qX8z/tu0nFy WVlm3ilqy8YSHy9f4Wx8a4bDh8OWX4ElsUbxrADuun/+7zYFsbiIL2/NQk3nexVF ZgWyoyJ2XlSkUn07ghjoBkNTvJ2GCh/G9QFaFQu8LfAXhj60XAcWOH0/lI0hPdCP 4JhAGZh1SDHoNxSFwriIw2k4GINLaHjGfDIQVvEtPwGOLJe9jH2KuuAdxahuT+yz tOn91ufpapxW9BUQoJHr/e6d0/CNqw== =gTcX -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2018-03-09-3' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for 4.17: UAPI Changes: plane: Add color encoding/range properties (Jyri) nouveau: Replace iturbt_709 property with color_encoding property (Ville) Core Changes: atomic: Move plane clipping into plane check helper (Ville) property: Multiple new property checks/verification (Ville) Driver Changes: rockchip: Fixes & improvements for rk3399/chromebook plus (various) sun4i: Add H3/H5 HDMI support (Jernej) i915: Add support for limited/full-range ycbcr toggling (Ville) pl111: Add bandwidth checking/limiting (Linus) Cc: Jernej Skrabec <jernej.skrabec@siol.net> Cc: Jyri Sarha <jsarha@ti.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Linus Walleij <linus.walleij@linaro.org> * tag 'drm-misc-next-2018-03-09-3' of git://anongit.freedesktop.org/drm/drm-misc: (85 commits) drm/rockchip: Don't use atomic constructs for psr drm/rockchip: analogix_dp: set psr activate/deactivate when enable/disable bridge drm/rockchip: dw_hdmi: Move HDMI vpll clock enable to bind() drm/rockchip: inno_hdmi: reorder clk_disable_unprepare call in unbind drm/rockchip: inno_hdmi: Fix error handling path. drm/rockchip: dw-mipi-dsi: Fix connector and encoder cleanup. drm/nouveau: Replace the iturbt_709 prop with the standard COLOR_ENCODING prop drm/pl111: Use max memory bandwidth for resolution drm/bridge: sii902x: Retry status read after DDI I2C drm/pl111: Handle the RealView variant separately drm/pl111: Make the default BPP a per-variant variable drm: simple_kms_helper: Fix .mode_valid() documentation bridge: Elaborate a bit on dumb VGA bridges in Kconfig drm/atomic: Add new reverse iterator over all plane state (V2) drm: Reject bad property flag combinations drm: Make property flags u32 drm/uapi: Deprecate DRM_MODE_PROP_PENDING drm: WARN when trying to add enum value > 63 to a bitmask property drm: WARN when trying add enum values to non-enum/bitmask properties drm: Reject replacing property enum values ...
This commit is contained in:
commit
0b8eeac5c6
|
@ -102,6 +102,7 @@ DWC HDMI PHY
|
|||
Required properties:
|
||||
- compatible: value must be one of:
|
||||
* allwinner,sun8i-a83t-hdmi-phy
|
||||
* allwinner,sun8i-h3-hdmi-phy
|
||||
- reg: base address and size of memory-mapped region
|
||||
- clocks: phandles to the clocks feeding the HDMI PHY
|
||||
* bus: the HDMI PHY interface clock
|
||||
|
@ -110,6 +111,9 @@ Required properties:
|
|||
- resets: phandle to the reset controller driving the PHY
|
||||
- reset-names: must be "phy"
|
||||
|
||||
H3 HDMI PHY requires additional clock:
|
||||
- pll-0: parent of phy clock
|
||||
|
||||
TV Encoder
|
||||
----------
|
||||
|
||||
|
@ -275,6 +279,7 @@ Required properties:
|
|||
- compatible: value must be one of:
|
||||
* allwinner,sun8i-a83t-de2-mixer-0
|
||||
* allwinner,sun8i-a83t-de2-mixer-1
|
||||
* allwinner,sun8i-h3-de2-mixer-0
|
||||
* allwinner,sun8i-v3s-de2-mixer
|
||||
- reg: base address and size of the memory-mapped region.
|
||||
- clocks: phandles to the clocks feeding the mixer
|
||||
|
@ -305,6 +310,7 @@ Required properties:
|
|||
* allwinner,sun7i-a20-display-engine
|
||||
* allwinner,sun8i-a33-display-engine
|
||||
* allwinner,sun8i-a83t-display-engine
|
||||
* allwinner,sun8i-h3-display-engine
|
||||
* allwinner,sun8i-v3s-display-engine
|
||||
|
||||
- allwinner,pipelines: list of phandle to the display engine
|
||||
|
|
|
@ -229,7 +229,6 @@ static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = {
|
|||
static int hdlcd_plane_atomic_check(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
struct drm_rect clip = { 0 };
|
||||
struct drm_crtc_state *crtc_state;
|
||||
u32 src_h = state->src_h >> 16;
|
||||
|
||||
|
@ -249,11 +248,7 @@ static int hdlcd_plane_atomic_check(struct drm_plane *plane,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (crtc_state->enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
return drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
|
||||
return drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
false, true);
|
||||
|
|
|
@ -141,18 +141,13 @@ static int malidp_se_check_scaling(struct malidp_plane *mp,
|
|||
struct drm_crtc_state *crtc_state =
|
||||
drm_atomic_get_existing_crtc_state(state->state, state->crtc);
|
||||
struct malidp_crtc_state *mc;
|
||||
struct drm_rect clip = { 0 };
|
||||
u32 src_w, src_h;
|
||||
int ret;
|
||||
|
||||
if (!crtc_state)
|
||||
return -EINVAL;
|
||||
|
||||
if (crtc_state->enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
|
||||
ret = drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
0, INT_MAX, true, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
@ -1200,13 +1200,14 @@ static int armada_drm_primary_update(struct drm_plane *plane,
|
|||
.crtc_h = crtc_h,
|
||||
.rotation = DRM_MODE_ROTATE_0,
|
||||
};
|
||||
const struct drm_rect clip = {
|
||||
.x2 = crtc->mode.hdisplay,
|
||||
.y2 = crtc->mode.vdisplay,
|
||||
struct drm_crtc_state crtc_state = {
|
||||
.crtc = crtc,
|
||||
.enable = crtc->enabled,
|
||||
.mode = crtc->mode,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(&state, crtc->state, &clip, 0,
|
||||
ret = drm_atomic_helper_check_plane_state(&state, &crtc_state, 0,
|
||||
INT_MAX, true, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
@ -205,9 +205,10 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
.crtc_h = crtc_h,
|
||||
.rotation = DRM_MODE_ROTATE_0,
|
||||
};
|
||||
const struct drm_rect clip = {
|
||||
.x2 = crtc->mode.hdisplay,
|
||||
.y2 = crtc->mode.vdisplay,
|
||||
struct drm_crtc_state crtc_state = {
|
||||
.crtc = crtc,
|
||||
.enable = crtc->enabled,
|
||||
.mode = crtc->mode,
|
||||
};
|
||||
int ret;
|
||||
|
||||
|
@ -215,7 +216,7 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
crtc_x, crtc_y, crtc_w, crtc_h,
|
||||
src_x, src_y, src_w, src_h);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(&state, crtc->state, &clip, 0,
|
||||
ret = drm_atomic_helper_check_plane_state(&state, &crtc_state, 0,
|
||||
INT_MAX, true, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
@ -30,7 +30,8 @@ config DRM_DUMB_VGA_DAC
|
|||
depends on OF
|
||||
select DRM_KMS_HELPER
|
||||
help
|
||||
Support for RGB to VGA DAC based bridges
|
||||
Support for non-programmable RGB to VGA DAC bridges, such as ADI
|
||||
ADV7123, TI THS8134 and THS8135 or passive resistor ladder DACs.
|
||||
|
||||
config DRM_LVDS_ENCODER
|
||||
tristate "Transparent parallel to LVDS encoder support"
|
||||
|
|
|
@ -98,17 +98,15 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int analogix_dp_psr_supported(struct device *dev)
|
||||
int analogix_dp_psr_supported(struct analogix_dp_device *dp)
|
||||
{
|
||||
struct analogix_dp_device *dp = dev_get_drvdata(dev);
|
||||
|
||||
return dp->psr_support;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(analogix_dp_psr_supported);
|
||||
|
||||
int analogix_dp_enable_psr(struct device *dev)
|
||||
int analogix_dp_enable_psr(struct analogix_dp_device *dp)
|
||||
{
|
||||
struct analogix_dp_device *dp = dev_get_drvdata(dev);
|
||||
struct edp_vsc_psr psr_vsc;
|
||||
|
||||
if (!dp->psr_support)
|
||||
|
@ -129,9 +127,8 @@ int analogix_dp_enable_psr(struct device *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(analogix_dp_enable_psr);
|
||||
|
||||
int analogix_dp_disable_psr(struct device *dev)
|
||||
int analogix_dp_disable_psr(struct analogix_dp_device *dp)
|
||||
{
|
||||
struct analogix_dp_device *dp = dev_get_drvdata(dev);
|
||||
struct edp_vsc_psr psr_vsc;
|
||||
int ret;
|
||||
|
||||
|
@ -1015,28 +1012,31 @@ static int analogix_dp_bridge_attach(struct drm_bridge *bridge)
|
|||
{
|
||||
struct analogix_dp_device *dp = bridge->driver_private;
|
||||
struct drm_encoder *encoder = dp->encoder;
|
||||
struct drm_connector *connector = &dp->connector;
|
||||
int ret;
|
||||
struct drm_connector *connector = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!bridge->encoder) {
|
||||
DRM_ERROR("Parent encoder object not found");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
if (!dp->plat_data->skip_connector) {
|
||||
connector = &dp->connector;
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
|
||||
ret = drm_connector_init(dp->drm_dev, connector,
|
||||
&analogix_dp_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_eDP);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to initialize connector with drm\n");
|
||||
return ret;
|
||||
ret = drm_connector_init(dp->drm_dev, connector,
|
||||
&analogix_dp_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_eDP);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to initialize connector with drm\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
drm_connector_helper_add(connector,
|
||||
&analogix_dp_connector_helper_funcs);
|
||||
drm_mode_connector_attach_encoder(connector, encoder);
|
||||
}
|
||||
|
||||
drm_connector_helper_add(connector,
|
||||
&analogix_dp_connector_helper_funcs);
|
||||
drm_mode_connector_attach_encoder(connector, encoder);
|
||||
|
||||
/*
|
||||
* NOTE: the connector registration is implemented in analogix
|
||||
* platform driver, that to say connector would be exist after
|
||||
|
@ -1279,8 +1279,9 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux,
|
|||
return analogix_dp_transfer(dp, msg);
|
||||
}
|
||||
|
||||
int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
|
||||
struct analogix_dp_plat_data *plat_data)
|
||||
struct analogix_dp_device *
|
||||
analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
|
||||
struct analogix_dp_plat_data *plat_data)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct analogix_dp_device *dp;
|
||||
|
@ -1290,14 +1291,12 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
|
|||
|
||||
if (!plat_data) {
|
||||
dev_err(dev, "Invalided input plat_data\n");
|
||||
return -EINVAL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL);
|
||||
if (!dp)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(dev, dp);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
dp->dev = &pdev->dev;
|
||||
dp->dpms_mode = DRM_MODE_DPMS_OFF;
|
||||
|
@ -1314,7 +1313,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
|
|||
|
||||
ret = analogix_dp_dt_parse_pdata(dp);
|
||||
if (ret)
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
|
||||
dp->phy = devm_phy_get(dp->dev, "dp");
|
||||
if (IS_ERR(dp->phy)) {
|
||||
|
@ -1328,14 +1327,14 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
|
|||
if (ret == -ENOSYS || ret == -ENODEV)
|
||||
dp->phy = NULL;
|
||||
else
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
}
|
||||
|
||||
dp->clock = devm_clk_get(&pdev->dev, "dp");
|
||||
if (IS_ERR(dp->clock)) {
|
||||
dev_err(&pdev->dev, "failed to get clock\n");
|
||||
return PTR_ERR(dp->clock);
|
||||
return ERR_CAST(dp->clock);
|
||||
}
|
||||
|
||||
clk_prepare_enable(dp->clock);
|
||||
|
@ -1344,7 +1343,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
|
|||
|
||||
dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(dp->reg_base))
|
||||
return PTR_ERR(dp->reg_base);
|
||||
return ERR_CAST(dp->reg_base);
|
||||
|
||||
dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd");
|
||||
|
||||
|
@ -1365,7 +1364,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
|
|||
"hpd_gpio");
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to get hpd gpio\n");
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
dp->irq = gpio_to_irq(dp->hpd_gpio);
|
||||
irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
|
||||
|
@ -1377,16 +1376,9 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
|
|||
|
||||
if (dp->irq == -ENXIO) {
|
||||
dev_err(&pdev->dev, "failed to get irq\n");
|
||||
return -ENODEV;
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
phy_power_on(dp->phy);
|
||||
|
||||
analogix_dp_init_dp(dp);
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, dp->irq,
|
||||
analogix_dp_hardirq,
|
||||
analogix_dp_irq_thread,
|
||||
|
@ -1406,38 +1398,30 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
|
|||
|
||||
ret = drm_dp_aux_register(&dp->aux);
|
||||
if (ret)
|
||||
goto err_disable_pm_runtime;
|
||||
return ERR_PTR(ret);
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
ret = analogix_dp_create_bridge(drm_dev, dp);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to create bridge (%d)\n", ret);
|
||||
drm_encoder_cleanup(dp->encoder);
|
||||
goto err_disable_pm_runtime;
|
||||
}
|
||||
|
||||
phy_power_off(dp->phy);
|
||||
pm_runtime_put(dev);
|
||||
|
||||
return 0;
|
||||
return dp;
|
||||
|
||||
err_disable_pm_runtime:
|
||||
|
||||
phy_power_off(dp->phy);
|
||||
pm_runtime_put(dev);
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(analogix_dp_bind);
|
||||
|
||||
void analogix_dp_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
void analogix_dp_unbind(struct analogix_dp_device *dp)
|
||||
{
|
||||
struct analogix_dp_device *dp = dev_get_drvdata(dev);
|
||||
|
||||
analogix_dp_bridge_disable(dp->bridge);
|
||||
dp->connector.funcs->destroy(&dp->connector);
|
||||
dp->encoder->funcs->destroy(dp->encoder);
|
||||
|
||||
if (dp->plat_data->panel) {
|
||||
if (drm_panel_unprepare(dp->plat_data->panel))
|
||||
|
@ -1447,16 +1431,14 @@ void analogix_dp_unbind(struct device *dev, struct device *master,
|
|||
}
|
||||
|
||||
drm_dp_aux_unregister(&dp->aux);
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_disable(dp->dev);
|
||||
clk_disable_unprepare(dp->clock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(analogix_dp_unbind);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int analogix_dp_suspend(struct device *dev)
|
||||
int analogix_dp_suspend(struct analogix_dp_device *dp)
|
||||
{
|
||||
struct analogix_dp_device *dp = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable_unprepare(dp->clock);
|
||||
|
||||
if (dp->plat_data->panel) {
|
||||
|
@ -1468,9 +1450,8 @@ int analogix_dp_suspend(struct device *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(analogix_dp_suspend);
|
||||
|
||||
int analogix_dp_resume(struct device *dev)
|
||||
int analogix_dp_resume(struct analogix_dp_device *dp)
|
||||
{
|
||||
struct analogix_dp_device *dp = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(dp->clock);
|
||||
|
|
|
@ -137,7 +137,9 @@ static int sii902x_get_modes(struct drm_connector *connector)
|
|||
struct sii902x *sii902x = connector_to_sii902x(connector);
|
||||
struct regmap *regmap = sii902x->regmap;
|
||||
u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
struct device *dev = &sii902x->i2c->dev;
|
||||
unsigned long timeout;
|
||||
unsigned int retries;
|
||||
unsigned int status;
|
||||
struct edid *edid;
|
||||
int num = 0;
|
||||
|
@ -159,7 +161,7 @@ static int sii902x_get_modes(struct drm_connector *connector)
|
|||
time_before(jiffies, timeout));
|
||||
|
||||
if (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
|
||||
dev_err(&sii902x->i2c->dev, "failed to acquire the i2c bus\n");
|
||||
dev_err(dev, "failed to acquire the i2c bus\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
|
@ -179,9 +181,19 @@ static int sii902x_get_modes(struct drm_connector *connector)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read(regmap, SII902X_SYS_CTRL_DATA, &status);
|
||||
/*
|
||||
* Sometimes the I2C bus can stall after failure to use the
|
||||
* EDID channel. Retry a few times to see if things clear
|
||||
* up, else continue anyway.
|
||||
*/
|
||||
retries = 5;
|
||||
do {
|
||||
ret = regmap_read(regmap, SII902X_SYS_CTRL_DATA,
|
||||
&status);
|
||||
retries--;
|
||||
} while (ret && retries);
|
||||
if (ret)
|
||||
return ret;
|
||||
dev_err(dev, "failed to read status (%d)\n", ret);
|
||||
|
||||
ret = regmap_update_bits(regmap, SII902X_SYS_CTRL_DATA,
|
||||
SII902X_SYS_CTRL_DDC_BUS_REQ |
|
||||
|
@ -201,7 +213,7 @@ static int sii902x_get_modes(struct drm_connector *connector)
|
|||
|
||||
if (status & (SII902X_SYS_CTRL_DDC_BUS_REQ |
|
||||
SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
|
||||
dev_err(&sii902x->i2c->dev, "failed to release the i2c bus\n");
|
||||
dev_err(dev, "failed to release the i2c bus\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
|
|
|
@ -1654,6 +1654,8 @@ static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
|
|||
* (v1.31a) and multiple Allwinner SoCs (v1.32a) have been identified
|
||||
* as needing the workaround, with 4 iterations for v1.30a and 1
|
||||
* iteration for others.
|
||||
* The Amlogic Meson GX SoCs (v2.01a) have been identified as needing
|
||||
* the workaround with a single iteration.
|
||||
*/
|
||||
|
||||
switch (hdmi->version) {
|
||||
|
@ -1662,6 +1664,7 @@ static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
|
|||
break;
|
||||
case 0x131a:
|
||||
case 0x132a:
|
||||
case 0x201a:
|
||||
count = 1;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -342,7 +342,7 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val)
|
|||
ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS,
|
||||
val, !(val & GEN_CMD_FULL), 1000,
|
||||
CMD_PKT_STATUS_TIMEOUT_US);
|
||||
if (ret < 0) {
|
||||
if (ret) {
|
||||
dev_err(dsi->dev, "failed to get available command FIFO\n");
|
||||
return ret;
|
||||
}
|
||||
|
@ -353,7 +353,7 @@ static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val)
|
|||
ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS,
|
||||
val, (val & mask) == mask,
|
||||
1000, CMD_PKT_STATUS_TIMEOUT_US);
|
||||
if (ret < 0) {
|
||||
if (ret) {
|
||||
dev_err(dsi->dev, "failed to write command FIFO\n");
|
||||
return ret;
|
||||
}
|
||||
|
@ -385,7 +385,7 @@ static int dw_mipi_dsi_write(struct dw_mipi_dsi *dsi,
|
|||
ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS,
|
||||
val, !(val & GEN_PLD_W_FULL), 1000,
|
||||
CMD_PKT_STATUS_TIMEOUT_US);
|
||||
if (ret < 0) {
|
||||
if (ret) {
|
||||
dev_err(dsi->dev,
|
||||
"failed to get available write payload FIFO\n");
|
||||
return ret;
|
||||
|
@ -721,13 +721,13 @@ static void dw_mipi_dsi_dphy_enable(struct dw_mipi_dsi *dsi)
|
|||
|
||||
ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, val,
|
||||
val & PHY_LOCK, 1000, PHY_STATUS_TIMEOUT_US);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
DRM_DEBUG_DRIVER("failed to wait phy lock state\n");
|
||||
|
||||
ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS,
|
||||
val, val & PHY_STOP_STATE_CLK_LANE, 1000,
|
||||
PHY_STATUS_TIMEOUT_US);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
DRM_DEBUG_DRIVER("failed to wait phy clk lane stop state\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -759,6 +759,10 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
|
|||
state->rotation = val;
|
||||
} else if (property == plane->zpos_property) {
|
||||
state->zpos = val;
|
||||
} else if (property == plane->color_encoding_property) {
|
||||
state->color_encoding = val;
|
||||
} else if (property == plane->color_range_property) {
|
||||
state->color_range = val;
|
||||
} else if (plane->funcs->atomic_set_property) {
|
||||
return plane->funcs->atomic_set_property(plane, state,
|
||||
property, val);
|
||||
|
@ -818,6 +822,10 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
|
|||
*val = state->rotation;
|
||||
} else if (property == plane->zpos_property) {
|
||||
*val = state->zpos;
|
||||
} else if (property == plane->color_encoding_property) {
|
||||
*val = state->color_encoding;
|
||||
} else if (property == plane->color_range_property) {
|
||||
*val = state->color_range;
|
||||
} else if (plane->funcs->atomic_get_property) {
|
||||
return plane->funcs->atomic_get_property(plane, state, property, val);
|
||||
} else {
|
||||
|
@ -882,12 +890,14 @@ static int drm_atomic_plane_check(struct drm_plane *plane,
|
|||
}
|
||||
|
||||
/* Check whether this plane supports the fb pixel format. */
|
||||
ret = drm_plane_check_pixel_format(plane, state->fb->format->format);
|
||||
ret = drm_plane_check_pixel_format(plane, state->fb->format->format,
|
||||
state->fb->modifier);
|
||||
if (ret) {
|
||||
struct drm_format_name_buf format_name;
|
||||
DRM_DEBUG_ATOMIC("Invalid pixel format %s\n",
|
||||
drm_get_format_name(state->fb->format->format,
|
||||
&format_name));
|
||||
DRM_DEBUG_ATOMIC("Invalid pixel format %s, modifier 0x%llx\n",
|
||||
drm_get_format_name(state->fb->format->format,
|
||||
&format_name),
|
||||
state->fb->modifier);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -944,6 +954,10 @@ static void drm_atomic_plane_print_state(struct drm_printer *p,
|
|||
drm_printf(p, "\tcrtc-pos=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&dest));
|
||||
drm_printf(p, "\tsrc-pos=" DRM_RECT_FP_FMT "\n", DRM_RECT_FP_ARG(&src));
|
||||
drm_printf(p, "\trotation=%x\n", state->rotation);
|
||||
drm_printf(p, "\tcolor-encoding=%s\n",
|
||||
drm_get_color_encoding_name(state->color_encoding));
|
||||
drm_printf(p, "\tcolor-range=%s\n",
|
||||
drm_get_color_range_name(state->color_range));
|
||||
|
||||
if (plane->funcs->atomic_print_state)
|
||||
plane->funcs->atomic_print_state(p, state);
|
||||
|
|
|
@ -699,7 +699,6 @@ EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
|
|||
* drm_atomic_helper_check_plane_state() - Check plane state for validity
|
||||
* @plane_state: plane state to check
|
||||
* @crtc_state: crtc state to check
|
||||
* @clip: integer clipping coordinates
|
||||
* @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
|
||||
* @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
|
||||
* @can_position: is it legal to position the plane such that it
|
||||
|
@ -719,7 +718,6 @@ EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
|
|||
*/
|
||||
int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
|
||||
const struct drm_crtc_state *crtc_state,
|
||||
const struct drm_rect *clip,
|
||||
int min_scale,
|
||||
int max_scale,
|
||||
bool can_position,
|
||||
|
@ -729,6 +727,7 @@ int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
|
|||
struct drm_rect *src = &plane_state->src;
|
||||
struct drm_rect *dst = &plane_state->dst;
|
||||
unsigned int rotation = plane_state->rotation;
|
||||
struct drm_rect clip = {};
|
||||
int hscale, vscale;
|
||||
|
||||
WARN_ON(plane_state->crtc && plane_state->crtc != crtc_state->crtc);
|
||||
|
@ -764,7 +763,10 @@ int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
|
|||
return -ERANGE;
|
||||
}
|
||||
|
||||
plane_state->visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale);
|
||||
if (crtc_state->enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->mode, &clip.x2, &clip.y2);
|
||||
|
||||
plane_state->visible = drm_rect_clip_scaled(src, dst, &clip, hscale, vscale);
|
||||
|
||||
drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation);
|
||||
|
||||
|
@ -778,10 +780,10 @@ int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
|
|||
*/
|
||||
return 0;
|
||||
|
||||
if (!can_position && !drm_rect_equals(dst, clip)) {
|
||||
if (!can_position && !drm_rect_equals(dst, &clip)) {
|
||||
DRM_DEBUG_KMS("Plane must cover entire CRTC\n");
|
||||
drm_rect_debug_print("dst: ", dst, false);
|
||||
drm_rect_debug_print("clip: ", clip, false);
|
||||
drm_rect_debug_print("clip: ", &clip, false);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,6 +88,20 @@
|
|||
* drm_mode_crtc_set_gamma_size(). Drivers which support both should use
|
||||
* drm_atomic_helper_legacy_gamma_set() to alias the legacy gamma ramp with the
|
||||
* "GAMMA_LUT" property above.
|
||||
*
|
||||
* Support for different non RGB color encodings is controlled through
|
||||
* &drm_plane specific COLOR_ENCODING and COLOR_RANGE properties. They
|
||||
* are set up by calling drm_plane_create_color_properties().
|
||||
*
|
||||
* "COLOR_ENCODING"
|
||||
* Optional plane enum property to support different non RGB
|
||||
* color encodings. The driver can provide a subset of standard
|
||||
* enum values supported by the DRM plane.
|
||||
*
|
||||
* "COLOR_RANGE"
|
||||
* Optional plane enum property to support different non RGB
|
||||
* color parameter ranges. The driver can provide a subset of
|
||||
* standard enum values supported by the DRM plane.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -339,3 +353,122 @@ out:
|
|||
drm_modeset_unlock(&crtc->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char * const color_encoding_name[] = {
|
||||
[DRM_COLOR_YCBCR_BT601] = "ITU-R BT.601 YCbCr",
|
||||
[DRM_COLOR_YCBCR_BT709] = "ITU-R BT.709 YCbCr",
|
||||
[DRM_COLOR_YCBCR_BT2020] = "ITU-R BT.2020 YCbCr",
|
||||
};
|
||||
|
||||
static const char * const color_range_name[] = {
|
||||
[DRM_COLOR_YCBCR_FULL_RANGE] = "YCbCr full range",
|
||||
[DRM_COLOR_YCBCR_LIMITED_RANGE] = "YCbCr limited range",
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_get_color_encoding_name - return a string for color encoding
|
||||
* @encoding: color encoding to compute name of
|
||||
*
|
||||
* In contrast to the other drm_get_*_name functions this one here returns a
|
||||
* const pointer and hence is threadsafe.
|
||||
*/
|
||||
const char *drm_get_color_encoding_name(enum drm_color_encoding encoding)
|
||||
{
|
||||
if (WARN_ON(encoding >= ARRAY_SIZE(color_encoding_name)))
|
||||
return "unknown";
|
||||
|
||||
return color_encoding_name[encoding];
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_get_color_range_name - return a string for color range
|
||||
* @range: color range to compute name of
|
||||
*
|
||||
* In contrast to the other drm_get_*_name functions this one here returns a
|
||||
* const pointer and hence is threadsafe.
|
||||
*/
|
||||
const char *drm_get_color_range_name(enum drm_color_range range)
|
||||
{
|
||||
if (WARN_ON(range >= ARRAY_SIZE(color_range_name)))
|
||||
return "unknown";
|
||||
|
||||
return color_range_name[range];
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_plane_create_color_properties - color encoding related plane properties
|
||||
* @plane: plane object
|
||||
* @supported_encodings: bitfield indicating supported color encodings
|
||||
* @supported_ranges: bitfileld indicating supported color ranges
|
||||
* @default_encoding: default color encoding
|
||||
* @default_range: default color range
|
||||
*
|
||||
* Create and attach plane specific COLOR_ENCODING and COLOR_RANGE
|
||||
* properties to @plane. The supported encodings and ranges should
|
||||
* be provided in supported_encodings and supported_ranges bitmasks.
|
||||
* Each bit set in the bitmask indicates that its number as enum
|
||||
* value is supported.
|
||||
*/
|
||||
int drm_plane_create_color_properties(struct drm_plane *plane,
|
||||
u32 supported_encodings,
|
||||
u32 supported_ranges,
|
||||
enum drm_color_encoding default_encoding,
|
||||
enum drm_color_range default_range)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_property *prop;
|
||||
struct drm_prop_enum_list enum_list[max(DRM_COLOR_ENCODING_MAX,
|
||||
DRM_COLOR_RANGE_MAX)];
|
||||
int i, len;
|
||||
|
||||
if (WARN_ON(supported_encodings == 0 ||
|
||||
(supported_encodings & -BIT(DRM_COLOR_ENCODING_MAX)) != 0 ||
|
||||
(supported_encodings & BIT(default_encoding)) == 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(supported_ranges == 0 ||
|
||||
(supported_ranges & -BIT(DRM_COLOR_RANGE_MAX)) != 0 ||
|
||||
(supported_ranges & BIT(default_range)) == 0))
|
||||
return -EINVAL;
|
||||
|
||||
len = 0;
|
||||
for (i = 0; i < DRM_COLOR_ENCODING_MAX; i++) {
|
||||
if ((supported_encodings & BIT(i)) == 0)
|
||||
continue;
|
||||
|
||||
enum_list[len].type = i;
|
||||
enum_list[len].name = color_encoding_name[i];
|
||||
len++;
|
||||
}
|
||||
|
||||
prop = drm_property_create_enum(dev, 0, "COLOR_ENCODING",
|
||||
enum_list, len);
|
||||
if (!prop)
|
||||
return -ENOMEM;
|
||||
plane->color_encoding_property = prop;
|
||||
drm_object_attach_property(&plane->base, prop, default_encoding);
|
||||
if (plane->state)
|
||||
plane->state->color_encoding = default_encoding;
|
||||
|
||||
len = 0;
|
||||
for (i = 0; i < DRM_COLOR_RANGE_MAX; i++) {
|
||||
if ((supported_ranges & BIT(i)) == 0)
|
||||
continue;
|
||||
|
||||
enum_list[len].type = i;
|
||||
enum_list[len].name = color_range_name[i];
|
||||
len++;
|
||||
}
|
||||
|
||||
prop = drm_property_create_enum(dev, 0, "COLOR_RANGE",
|
||||
enum_list, len);
|
||||
if (!prop)
|
||||
return -ENOMEM;
|
||||
plane->color_range_property = prop;
|
||||
drm_object_attach_property(&plane->base, prop, default_range);
|
||||
if (plane->state)
|
||||
plane->state->color_range = default_range;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_plane_create_color_properties);
|
||||
|
|
|
@ -629,12 +629,14 @@ retry:
|
|||
*/
|
||||
if (!crtc->primary->format_default) {
|
||||
ret = drm_plane_check_pixel_format(crtc->primary,
|
||||
fb->format->format);
|
||||
fb->format->format,
|
||||
fb->modifier);
|
||||
if (ret) {
|
||||
struct drm_format_name_buf format_name;
|
||||
DRM_DEBUG_KMS("Invalid pixel format %s\n",
|
||||
drm_get_format_name(fb->format->format,
|
||||
&format_name));
|
||||
DRM_DEBUG_KMS("Invalid pixel format %s, modifier 0x%llx\n",
|
||||
drm_get_format_name(fb->format->format,
|
||||
&format_name),
|
||||
fb->modifier);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,8 @@ int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
|
|||
void *data, struct drm_file *file_priv);
|
||||
|
||||
/* drm_color_mgmt.c */
|
||||
const char *drm_get_color_encoding_name(enum drm_color_encoding encoding);
|
||||
const char *drm_get_color_range_name(enum drm_color_range range);
|
||||
|
||||
/* IOCTLs */
|
||||
int drm_mode_gamma_get_ioctl(struct drm_device *dev,
|
||||
|
@ -196,8 +198,8 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
|
|||
/* drm_plane.c */
|
||||
int drm_plane_register_all(struct drm_device *dev);
|
||||
void drm_plane_unregister_all(struct drm_device *dev);
|
||||
int drm_plane_check_pixel_format(const struct drm_plane *plane,
|
||||
u32 format);
|
||||
int drm_plane_check_pixel_format(struct drm_plane *plane,
|
||||
u32 format, u64 modifier);
|
||||
|
||||
/* drm_bridge.c */
|
||||
void drm_bridge_detach(struct drm_bridge *bridge);
|
||||
|
|
|
@ -99,7 +99,7 @@ static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
|
|||
case DRM_MINOR_CONTROL:
|
||||
return &dev->control;
|
||||
default:
|
||||
return NULL;
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ EXPORT_SYMBOL(drm_legacy_ioremapfree);
|
|||
u64 drm_get_max_iomem(void)
|
||||
{
|
||||
struct resource *tmp;
|
||||
u64 max_iomem = 0;
|
||||
resource_size_t max_iomem = 0;
|
||||
|
||||
for (tmp = iomem_resource.child; tmp; tmp = tmp->sibling) {
|
||||
max_iomem = max(max_iomem, tmp->end);
|
||||
|
|
|
@ -180,7 +180,7 @@ static void drm_mm_interval_tree_add_node(struct drm_mm_node *hole_node,
|
|||
struct drm_mm *mm = hole_node->mm;
|
||||
struct rb_node **link, *rb;
|
||||
struct drm_mm_node *parent;
|
||||
bool leftmost = true;
|
||||
bool leftmost;
|
||||
|
||||
node->__subtree_last = LAST(node);
|
||||
|
||||
|
@ -201,6 +201,7 @@ static void drm_mm_interval_tree_add_node(struct drm_mm_node *hole_node,
|
|||
} else {
|
||||
rb = NULL;
|
||||
link = &mm->interval_tree.rb_root.rb_node;
|
||||
leftmost = true;
|
||||
}
|
||||
|
||||
while (*link) {
|
||||
|
@ -208,11 +209,11 @@ static void drm_mm_interval_tree_add_node(struct drm_mm_node *hole_node,
|
|||
parent = rb_entry(rb, struct drm_mm_node, rb);
|
||||
if (parent->__subtree_last < node->__subtree_last)
|
||||
parent->__subtree_last = node->__subtree_last;
|
||||
if (node->start < parent->start)
|
||||
if (node->start < parent->start) {
|
||||
link = &parent->rb.rb_left;
|
||||
else {
|
||||
} else {
|
||||
link = &parent->rb.rb_right;
|
||||
leftmost = true;
|
||||
leftmost = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -113,6 +113,7 @@ retry:
|
|||
kfree(ctx);
|
||||
return;
|
||||
}
|
||||
ww_acquire_done(&ctx->ww_ctx);
|
||||
|
||||
WARN_ON(config->acquire_ctx);
|
||||
|
||||
|
|
|
@ -122,12 +122,10 @@ int drm_of_component_probe(struct device *dev,
|
|||
if (!port)
|
||||
break;
|
||||
|
||||
if (!of_device_is_available(port->parent)) {
|
||||
of_node_put(port);
|
||||
continue;
|
||||
}
|
||||
if (of_device_is_available(port->parent))
|
||||
drm_of_component_match_add(dev, &match, compare_of,
|
||||
port);
|
||||
|
||||
drm_of_component_match_add(dev, &match, compare_of, port);
|
||||
of_node_put(port);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/dmi.h>
|
||||
#include <linux/module.h>
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_utils.h>
|
||||
|
||||
#ifdef CONFIG_DMI
|
||||
|
||||
|
|
|
@ -549,16 +549,33 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format)
|
||||
int drm_plane_check_pixel_format(struct drm_plane *plane,
|
||||
u32 format, u64 modifier)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < plane->format_count; i++) {
|
||||
if (format == plane->format_types[i])
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
if (i == plane->format_count)
|
||||
return -EINVAL;
|
||||
|
||||
return -EINVAL;
|
||||
if (!plane->modifier_count)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < plane->modifier_count; i++) {
|
||||
if (modifier == plane->modifiers[i])
|
||||
break;
|
||||
}
|
||||
if (i == plane->modifier_count)
|
||||
return -EINVAL;
|
||||
|
||||
if (plane->funcs->format_mod_supported &&
|
||||
!plane->funcs->format_mod_supported(plane, format, modifier))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -602,12 +619,14 @@ static int __setplane_internal(struct drm_plane *plane,
|
|||
}
|
||||
|
||||
/* Check whether this plane supports the fb pixel format. */
|
||||
ret = drm_plane_check_pixel_format(plane, fb->format->format);
|
||||
ret = drm_plane_check_pixel_format(plane, fb->format->format,
|
||||
fb->modifier);
|
||||
if (ret) {
|
||||
struct drm_format_name_buf format_name;
|
||||
DRM_DEBUG_KMS("Invalid pixel format %s\n",
|
||||
drm_get_format_name(fb->format->format,
|
||||
&format_name));
|
||||
DRM_DEBUG_KMS("Invalid pixel format %s, modifier 0x%llx\n",
|
||||
drm_get_format_name(fb->format->format,
|
||||
&format_name),
|
||||
fb->modifier);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
|
@ -106,7 +106,6 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc,
|
|||
* @fb: framebuffer to flip onto plane
|
||||
* @src: source coordinates in 16.16 fixed point
|
||||
* @dst: integer destination coordinates
|
||||
* @clip: integer clipping coordinates
|
||||
* @rotation: plane rotation
|
||||
* @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
|
||||
* @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
|
||||
|
@ -131,7 +130,6 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
|
|||
struct drm_framebuffer *fb,
|
||||
struct drm_rect *src,
|
||||
struct drm_rect *dst,
|
||||
const struct drm_rect *clip,
|
||||
unsigned int rotation,
|
||||
int min_scale,
|
||||
int max_scale,
|
||||
|
@ -157,11 +155,12 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
|
|||
struct drm_crtc_state crtc_state = {
|
||||
.crtc = crtc,
|
||||
.enable = crtc->enabled,
|
||||
.mode = crtc->mode,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
|
||||
clip, min_scale, max_scale,
|
||||
min_scale, max_scale,
|
||||
can_position,
|
||||
can_update_disabled);
|
||||
if (ret)
|
||||
|
@ -239,16 +238,12 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
.x2 = crtc_x + crtc_w,
|
||||
.y2 = crtc_y + crtc_h,
|
||||
};
|
||||
const struct drm_rect clip = {
|
||||
.x2 = crtc->mode.hdisplay,
|
||||
.y2 = crtc->mode.vdisplay,
|
||||
};
|
||||
struct drm_connector **connector_list;
|
||||
int num_connectors, ret;
|
||||
bool visible;
|
||||
|
||||
ret = drm_plane_helper_check_update(plane, crtc, fb,
|
||||
&src, &dest, &clip,
|
||||
&src, &dest,
|
||||
DRM_MODE_ROTATE_0,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
|
|
|
@ -230,26 +230,26 @@ void drm_gem_map_detach(struct dma_buf *dma_buf,
|
|||
struct drm_prime_attachment *prime_attach = attach->priv;
|
||||
struct drm_gem_object *obj = dma_buf->priv;
|
||||
struct drm_device *dev = obj->dev;
|
||||
struct sg_table *sgt;
|
||||
|
||||
if (prime_attach) {
|
||||
struct sg_table *sgt = prime_attach->sgt;
|
||||
|
||||
if (sgt) {
|
||||
if (prime_attach->dir != DMA_NONE)
|
||||
dma_unmap_sg_attrs(attach->dev, sgt->sgl,
|
||||
sgt->nents,
|
||||
prime_attach->dir,
|
||||
DMA_ATTR_SKIP_CPU_SYNC);
|
||||
sg_free_table(sgt);
|
||||
}
|
||||
|
||||
kfree(sgt);
|
||||
kfree(prime_attach);
|
||||
attach->priv = NULL;
|
||||
}
|
||||
|
||||
if (dev->driver->gem_prime_unpin)
|
||||
dev->driver->gem_prime_unpin(obj);
|
||||
|
||||
if (!prime_attach)
|
||||
return;
|
||||
|
||||
sgt = prime_attach->sgt;
|
||||
if (sgt) {
|
||||
if (prime_attach->dir != DMA_NONE)
|
||||
dma_unmap_sg_attrs(attach->dev, sgt->sgl, sgt->nents,
|
||||
prime_attach->dir,
|
||||
DMA_ATTR_SKIP_CPU_SYNC);
|
||||
sg_free_table(sgt);
|
||||
}
|
||||
|
||||
kfree(sgt);
|
||||
kfree(prime_attach);
|
||||
attach->priv = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_map_detach);
|
||||
|
||||
|
@ -922,40 +922,40 @@ EXPORT_SYMBOL(drm_prime_pages_to_sg);
|
|||
/**
|
||||
* drm_prime_sg_to_page_addr_arrays - convert an sg table into a page array
|
||||
* @sgt: scatter-gather table to convert
|
||||
* @pages: array of page pointers to store the page array in
|
||||
* @pages: optional array of page pointers to store the page array in
|
||||
* @addrs: optional array to store the dma bus address of each page
|
||||
* @max_pages: size of both the passed-in arrays
|
||||
* @max_entries: size of both the passed-in arrays
|
||||
*
|
||||
* Exports an sg table into an array of pages and addresses. This is currently
|
||||
* required by the TTM driver in order to do correct fault handling.
|
||||
*/
|
||||
int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
|
||||
dma_addr_t *addrs, int max_pages)
|
||||
dma_addr_t *addrs, int max_entries)
|
||||
{
|
||||
unsigned count;
|
||||
struct scatterlist *sg;
|
||||
struct page *page;
|
||||
u32 len;
|
||||
int pg_index;
|
||||
u32 len, index;
|
||||
dma_addr_t addr;
|
||||
|
||||
pg_index = 0;
|
||||
index = 0;
|
||||
for_each_sg(sgt->sgl, sg, sgt->nents, count) {
|
||||
len = sg->length;
|
||||
page = sg_page(sg);
|
||||
addr = sg_dma_address(sg);
|
||||
|
||||
while (len > 0) {
|
||||
if (WARN_ON(pg_index >= max_pages))
|
||||
if (WARN_ON(index >= max_entries))
|
||||
return -1;
|
||||
pages[pg_index] = page;
|
||||
if (pages)
|
||||
pages[index] = page;
|
||||
if (addrs)
|
||||
addrs[pg_index] = addr;
|
||||
addrs[index] = addr;
|
||||
|
||||
page++;
|
||||
addr += PAGE_SIZE;
|
||||
len -= PAGE_SIZE;
|
||||
pg_index++;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -50,11 +50,27 @@
|
|||
* IOCTL and in the get/set property IOCTL.
|
||||
*/
|
||||
|
||||
static bool drm_property_type_valid(struct drm_property *property)
|
||||
static bool drm_property_flags_valid(u32 flags)
|
||||
{
|
||||
if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
|
||||
return !(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
|
||||
return !!(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
|
||||
u32 legacy_type = flags & DRM_MODE_PROP_LEGACY_TYPE;
|
||||
u32 ext_type = flags & DRM_MODE_PROP_EXTENDED_TYPE;
|
||||
|
||||
/* Reject undefined/deprecated flags */
|
||||
if (flags & ~(DRM_MODE_PROP_LEGACY_TYPE |
|
||||
DRM_MODE_PROP_EXTENDED_TYPE |
|
||||
DRM_MODE_PROP_IMMUTABLE |
|
||||
DRM_MODE_PROP_ATOMIC))
|
||||
return false;
|
||||
|
||||
/* We want either a legacy type or an extended type, but not both */
|
||||
if (!legacy_type == !ext_type)
|
||||
return false;
|
||||
|
||||
/* Only one legacy type at a time please */
|
||||
if (legacy_type && !is_power_of_2(legacy_type))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,12 +88,19 @@ static bool drm_property_type_valid(struct drm_property *property)
|
|||
* Returns:
|
||||
* A pointer to the newly created property on success, NULL on failure.
|
||||
*/
|
||||
struct drm_property *drm_property_create(struct drm_device *dev, int flags,
|
||||
const char *name, int num_values)
|
||||
struct drm_property *drm_property_create(struct drm_device *dev,
|
||||
u32 flags, const char *name,
|
||||
int num_values)
|
||||
{
|
||||
struct drm_property *property = NULL;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(!drm_property_flags_valid(flags)))
|
||||
return NULL;
|
||||
|
||||
if (WARN_ON(strlen(name) >= DRM_PROP_NAME_LEN))
|
||||
return NULL;
|
||||
|
||||
property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
|
||||
if (!property)
|
||||
return NULL;
|
||||
|
@ -99,15 +122,11 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,
|
|||
property->num_values = num_values;
|
||||
INIT_LIST_HEAD(&property->enum_list);
|
||||
|
||||
if (name) {
|
||||
strncpy(property->name, name, DRM_PROP_NAME_LEN);
|
||||
property->name[DRM_PROP_NAME_LEN-1] = '\0';
|
||||
}
|
||||
strncpy(property->name, name, DRM_PROP_NAME_LEN);
|
||||
property->name[DRM_PROP_NAME_LEN-1] = '\0';
|
||||
|
||||
list_add_tail(&property->head, &dev->mode_config.property_list);
|
||||
|
||||
WARN_ON(!drm_property_type_valid(property));
|
||||
|
||||
return property;
|
||||
fail:
|
||||
kfree(property->values);
|
||||
|
@ -135,10 +154,10 @@ EXPORT_SYMBOL(drm_property_create);
|
|||
* Returns:
|
||||
* A pointer to the newly created property on success, NULL on failure.
|
||||
*/
|
||||
struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
|
||||
const char *name,
|
||||
const struct drm_prop_enum_list *props,
|
||||
int num_values)
|
||||
struct drm_property *drm_property_create_enum(struct drm_device *dev,
|
||||
u32 flags, const char *name,
|
||||
const struct drm_prop_enum_list *props,
|
||||
int num_values)
|
||||
{
|
||||
struct drm_property *property;
|
||||
int i, ret;
|
||||
|
@ -184,10 +203,10 @@ EXPORT_SYMBOL(drm_property_create_enum);
|
|||
* A pointer to the newly created property on success, NULL on failure.
|
||||
*/
|
||||
struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
|
||||
int flags, const char *name,
|
||||
const struct drm_prop_enum_list *props,
|
||||
int num_props,
|
||||
uint64_t supported_bits)
|
||||
u32 flags, const char *name,
|
||||
const struct drm_prop_enum_list *props,
|
||||
int num_props,
|
||||
uint64_t supported_bits)
|
||||
{
|
||||
struct drm_property *property;
|
||||
int i, ret, index = 0;
|
||||
|
@ -221,8 +240,8 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
|
|||
EXPORT_SYMBOL(drm_property_create_bitmask);
|
||||
|
||||
static struct drm_property *property_create_range(struct drm_device *dev,
|
||||
int flags, const char *name,
|
||||
uint64_t min, uint64_t max)
|
||||
u32 flags, const char *name,
|
||||
uint64_t min, uint64_t max)
|
||||
{
|
||||
struct drm_property *property;
|
||||
|
||||
|
@ -255,9 +274,9 @@ static struct drm_property *property_create_range(struct drm_device *dev,
|
|||
* Returns:
|
||||
* A pointer to the newly created property on success, NULL on failure.
|
||||
*/
|
||||
struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
|
||||
const char *name,
|
||||
uint64_t min, uint64_t max)
|
||||
struct drm_property *drm_property_create_range(struct drm_device *dev,
|
||||
u32 flags, const char *name,
|
||||
uint64_t min, uint64_t max)
|
||||
{
|
||||
return property_create_range(dev, DRM_MODE_PROP_RANGE | flags,
|
||||
name, min, max);
|
||||
|
@ -284,8 +303,8 @@ EXPORT_SYMBOL(drm_property_create_range);
|
|||
* A pointer to the newly created property on success, NULL on failure.
|
||||
*/
|
||||
struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
|
||||
int flags, const char *name,
|
||||
int64_t min, int64_t max)
|
||||
u32 flags, const char *name,
|
||||
int64_t min, int64_t max)
|
||||
{
|
||||
return property_create_range(dev, DRM_MODE_PROP_SIGNED_RANGE | flags,
|
||||
name, I642U64(min), I642U64(max));
|
||||
|
@ -311,7 +330,7 @@ EXPORT_SYMBOL(drm_property_create_signed_range);
|
|||
* A pointer to the newly created property on success, NULL on failure.
|
||||
*/
|
||||
struct drm_property *drm_property_create_object(struct drm_device *dev,
|
||||
int flags, const char *name,
|
||||
u32 flags, const char *name,
|
||||
uint32_t type)
|
||||
{
|
||||
struct drm_property *property;
|
||||
|
@ -347,8 +366,8 @@ EXPORT_SYMBOL(drm_property_create_object);
|
|||
* Returns:
|
||||
* A pointer to the newly created property on success, NULL on failure.
|
||||
*/
|
||||
struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
|
||||
const char *name)
|
||||
struct drm_property *drm_property_create_bool(struct drm_device *dev,
|
||||
u32 flags, const char *name)
|
||||
{
|
||||
return drm_property_create_range(dev, flags, name, 0, 1);
|
||||
}
|
||||
|
@ -374,26 +393,24 @@ int drm_property_add_enum(struct drm_property *property, int index,
|
|||
{
|
||||
struct drm_property_enum *prop_enum;
|
||||
|
||||
if (!(drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
|
||||
drm_property_type_is(property, DRM_MODE_PROP_BITMASK)))
|
||||
if (WARN_ON(strlen(name) >= DRM_PROP_NAME_LEN))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(!drm_property_type_is(property, DRM_MODE_PROP_ENUM) &&
|
||||
!drm_property_type_is(property, DRM_MODE_PROP_BITMASK)))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Bitmask enum properties have the additional constraint of values
|
||||
* from 0 to 63
|
||||
*/
|
||||
if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
|
||||
(value > 63))
|
||||
if (WARN_ON(drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
|
||||
value > 63))
|
||||
return -EINVAL;
|
||||
|
||||
if (!list_empty(&property->enum_list)) {
|
||||
list_for_each_entry(prop_enum, &property->enum_list, head) {
|
||||
if (prop_enum->value == value) {
|
||||
strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
|
||||
prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
list_for_each_entry(prop_enum, &property->enum_list, head) {
|
||||
if (WARN_ON(prop_enum->value == value))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
|
||||
|
|
|
@ -92,6 +92,28 @@ static const struct drm_crtc_helper_funcs drm_simple_kms_crtc_helper_funcs = {
|
|||
.atomic_disable = drm_simple_kms_crtc_disable,
|
||||
};
|
||||
|
||||
static int drm_simple_kms_crtc_enable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_simple_display_pipe *pipe;
|
||||
|
||||
pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
|
||||
if (!pipe->funcs || !pipe->funcs->enable_vblank)
|
||||
return 0;
|
||||
|
||||
return pipe->funcs->enable_vblank(pipe);
|
||||
}
|
||||
|
||||
static void drm_simple_kms_crtc_disable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_simple_display_pipe *pipe;
|
||||
|
||||
pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
|
||||
if (!pipe->funcs || !pipe->funcs->disable_vblank)
|
||||
return;
|
||||
|
||||
pipe->funcs->disable_vblank(pipe);
|
||||
}
|
||||
|
||||
static const struct drm_crtc_funcs drm_simple_kms_crtc_funcs = {
|
||||
.reset = drm_atomic_helper_crtc_reset,
|
||||
.destroy = drm_crtc_cleanup,
|
||||
|
@ -99,12 +121,13 @@ static const struct drm_crtc_funcs drm_simple_kms_crtc_funcs = {
|
|||
.page_flip = drm_atomic_helper_page_flip,
|
||||
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
|
||||
.enable_vblank = drm_simple_kms_crtc_enable_vblank,
|
||||
.disable_vblank = drm_simple_kms_crtc_disable_vblank,
|
||||
};
|
||||
|
||||
static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane,
|
||||
struct drm_plane_state *plane_state)
|
||||
{
|
||||
struct drm_rect clip = { 0 };
|
||||
struct drm_simple_display_pipe *pipe;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
int ret;
|
||||
|
@ -112,15 +135,8 @@ static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane,
|
|||
pipe = container_of(plane, struct drm_simple_display_pipe, plane);
|
||||
crtc_state = drm_atomic_get_new_crtc_state(plane_state->state,
|
||||
&pipe->crtc);
|
||||
if (!crtc_state->enable)
|
||||
return 0; /* nothing to check when disabling or disabled */
|
||||
|
||||
if (crtc_state->enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state,
|
||||
&clip,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
false, true);
|
||||
|
@ -128,7 +144,7 @@ static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane,
|
|||
return ret;
|
||||
|
||||
if (!plane_state->visible)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
|
||||
if (!pipe->funcs || !pipe->funcs->check)
|
||||
return 0;
|
||||
|
|
|
@ -120,6 +120,9 @@ static u32 __get_vblank_counter(struct drm_device *dev, unsigned int pipe)
|
|||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
|
||||
|
||||
if (WARN_ON(!crtc))
|
||||
return 0;
|
||||
|
||||
if (crtc->funcs->get_vblank_counter)
|
||||
return crtc->funcs->get_vblank_counter(crtc);
|
||||
}
|
||||
|
@ -318,6 +321,9 @@ static void __disable_vblank(struct drm_device *dev, unsigned int pipe)
|
|||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
|
||||
|
||||
if (WARN_ON(!crtc))
|
||||
return;
|
||||
|
||||
if (crtc->funcs->disable_vblank) {
|
||||
crtc->funcs->disable_vblank(crtc);
|
||||
return;
|
||||
|
@ -920,6 +926,9 @@ static int __enable_vblank(struct drm_device *dev, unsigned int pipe)
|
|||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
|
||||
|
||||
if (WARN_ON(!crtc))
|
||||
return 0;
|
||||
|
||||
if (crtc->funcs->enable_vblank)
|
||||
return crtc->funcs->enable_vblank(crtc);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ struct exynos_dp_device {
|
|||
struct device *dev;
|
||||
|
||||
struct videomode vm;
|
||||
struct analogix_dp_device *adp;
|
||||
struct analogix_dp_plat_data plat_data;
|
||||
};
|
||||
|
||||
|
@ -157,13 +158,6 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
|
|||
struct drm_device *drm_dev = data;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Just like the probe function said, we don't need the
|
||||
* device drvrate anymore, we should leave the charge to
|
||||
* analogix dp driver, set the device drvdata to NULL.
|
||||
*/
|
||||
dev_set_drvdata(dev, NULL);
|
||||
|
||||
dp->dev = dev;
|
||||
dp->drm_dev = drm_dev;
|
||||
|
||||
|
@ -190,13 +184,22 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
|
|||
|
||||
dp->plat_data.encoder = encoder;
|
||||
|
||||
return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
|
||||
dp->adp = analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
|
||||
if (IS_ERR(dp->adp)) {
|
||||
dp->encoder.funcs->destroy(&dp->encoder);
|
||||
return PTR_ERR(dp->adp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void exynos_dp_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
return analogix_dp_unbind(dev, master, data);
|
||||
struct exynos_dp_device *dp = dev_get_drvdata(dev);
|
||||
|
||||
analogix_dp_unbind(dp->adp);
|
||||
dp->encoder.funcs->destroy(&dp->encoder);
|
||||
}
|
||||
|
||||
static const struct component_ops exynos_dp_ops = {
|
||||
|
@ -241,6 +244,7 @@ static int exynos_dp_probe(struct platform_device *pdev)
|
|||
|
||||
/* The remote port can be either a panel or a bridge */
|
||||
dp->plat_data.panel = panel;
|
||||
dp->plat_data.skip_connector = !!bridge;
|
||||
dp->ptn_bridge = bridge;
|
||||
|
||||
out:
|
||||
|
@ -257,12 +261,16 @@ static int exynos_dp_remove(struct platform_device *pdev)
|
|||
#ifdef CONFIG_PM
|
||||
static int exynos_dp_suspend(struct device *dev)
|
||||
{
|
||||
return analogix_dp_suspend(dev);
|
||||
struct exynos_dp_device *dp = dev_get_drvdata(dev);
|
||||
|
||||
return analogix_dp_suspend(dp->adp);
|
||||
}
|
||||
|
||||
static int exynos_dp_resume(struct device *dev)
|
||||
{
|
||||
return analogix_dp_resume(dev);
|
||||
struct exynos_dp_device *dp = dev_get_drvdata(dev);
|
||||
|
||||
return analogix_dp_resume(dp->adp);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -6132,6 +6132,7 @@ enum {
|
|||
#define _DVSACNTR 0x72180
|
||||
#define DVS_ENABLE (1<<31)
|
||||
#define DVS_GAMMA_ENABLE (1<<30)
|
||||
#define DVS_YUV_RANGE_CORRECTION_DISABLE (1<<27)
|
||||
#define DVS_PIXFORMAT_MASK (3<<25)
|
||||
#define DVS_FORMAT_YUV422 (0<<25)
|
||||
#define DVS_FORMAT_RGBX101010 (1<<25)
|
||||
|
@ -6140,6 +6141,7 @@ enum {
|
|||
#define DVS_PIPE_CSC_ENABLE (1<<24)
|
||||
#define DVS_SOURCE_KEY (1<<22)
|
||||
#define DVS_RGB_ORDER_XBGR (1<<20)
|
||||
#define DVS_YUV_FORMAT_BT709 (1<<18)
|
||||
#define DVS_YUV_BYTE_ORDER_MASK (3<<16)
|
||||
#define DVS_YUV_ORDER_YUYV (0<<16)
|
||||
#define DVS_YUV_ORDER_UYVY (1<<16)
|
||||
|
@ -6199,6 +6201,7 @@ enum {
|
|||
#define _SPRA_CTL 0x70280
|
||||
#define SPRITE_ENABLE (1<<31)
|
||||
#define SPRITE_GAMMA_ENABLE (1<<30)
|
||||
#define SPRITE_YUV_RANGE_CORRECTION_DISABLE (1<<28)
|
||||
#define SPRITE_PIXFORMAT_MASK (7<<25)
|
||||
#define SPRITE_FORMAT_YUV422 (0<<25)
|
||||
#define SPRITE_FORMAT_RGBX101010 (1<<25)
|
||||
|
@ -6210,7 +6213,7 @@ enum {
|
|||
#define SPRITE_SOURCE_KEY (1<<22)
|
||||
#define SPRITE_RGB_ORDER_RGBX (1<<20) /* only for 888 and 161616 */
|
||||
#define SPRITE_YUV_TO_RGB_CSC_DISABLE (1<<19)
|
||||
#define SPRITE_YUV_CSC_FORMAT_BT709 (1<<18) /* 0 is BT601 */
|
||||
#define SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709 (1<<18) /* 0 is BT601 */
|
||||
#define SPRITE_YUV_BYTE_ORDER_MASK (3<<16)
|
||||
#define SPRITE_YUV_ORDER_YUYV (0<<16)
|
||||
#define SPRITE_YUV_ORDER_UYVY (1<<16)
|
||||
|
@ -6286,6 +6289,7 @@ enum {
|
|||
#define SP_FORMAT_RGBA8888 (0xf<<26)
|
||||
#define SP_ALPHA_PREMULTIPLY (1<<23) /* CHV pipe B */
|
||||
#define SP_SOURCE_KEY (1<<22)
|
||||
#define SP_YUV_FORMAT_BT709 (1<<18)
|
||||
#define SP_YUV_BYTE_ORDER_MASK (3<<16)
|
||||
#define SP_YUV_ORDER_YUYV (0<<16)
|
||||
#define SP_YUV_ORDER_UYVY (1<<16)
|
||||
|
@ -6305,6 +6309,12 @@ enum {
|
|||
#define _SPATILEOFF (VLV_DISPLAY_BASE + 0x721a4)
|
||||
#define _SPACONSTALPHA (VLV_DISPLAY_BASE + 0x721a8)
|
||||
#define SP_CONST_ALPHA_ENABLE (1<<31)
|
||||
#define _SPACLRC0 (VLV_DISPLAY_BASE + 0x721d0)
|
||||
#define SP_CONTRAST(x) ((x) << 18) /* u3.6 */
|
||||
#define SP_BRIGHTNESS(x) ((x) & 0xff) /* s8 */
|
||||
#define _SPACLRC1 (VLV_DISPLAY_BASE + 0x721d4)
|
||||
#define SP_SH_SIN(x) (((x) & 0x7ff) << 16) /* s4.7 */
|
||||
#define SP_SH_COS(x) (x) /* u3.7 */
|
||||
#define _SPAGAMC (VLV_DISPLAY_BASE + 0x721f4)
|
||||
|
||||
#define _SPBCNTR (VLV_DISPLAY_BASE + 0x72280)
|
||||
|
@ -6318,6 +6328,8 @@ enum {
|
|||
#define _SPBKEYMAXVAL (VLV_DISPLAY_BASE + 0x722a0)
|
||||
#define _SPBTILEOFF (VLV_DISPLAY_BASE + 0x722a4)
|
||||
#define _SPBCONSTALPHA (VLV_DISPLAY_BASE + 0x722a8)
|
||||
#define _SPBCLRC0 (VLV_DISPLAY_BASE + 0x722d0)
|
||||
#define _SPBCLRC1 (VLV_DISPLAY_BASE + 0x722d4)
|
||||
#define _SPBGAMC (VLV_DISPLAY_BASE + 0x722f4)
|
||||
|
||||
#define _MMIO_VLV_SPR(pipe, plane_id, reg_a, reg_b) \
|
||||
|
@ -6334,6 +6346,8 @@ enum {
|
|||
#define SPKEYMAXVAL(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPAKEYMAXVAL, _SPBKEYMAXVAL)
|
||||
#define SPTILEOFF(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPATILEOFF, _SPBTILEOFF)
|
||||
#define SPCONSTALPHA(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPACONSTALPHA, _SPBCONSTALPHA)
|
||||
#define SPCLRC0(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPACLRC0, _SPBCLRC0)
|
||||
#define SPCLRC1(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPACLRC1, _SPBCLRC1)
|
||||
#define SPGAMC(pipe, plane_id) _MMIO_VLV_SPR((pipe), (plane_id), _SPAGAMC, _SPBGAMC)
|
||||
|
||||
/*
|
||||
|
@ -6379,6 +6393,7 @@ enum {
|
|||
#define _PLANE_CTL_3_A 0x70380
|
||||
#define PLANE_CTL_ENABLE (1 << 31)
|
||||
#define PLANE_CTL_PIPE_GAMMA_ENABLE (1 << 30) /* Pre-GLK */
|
||||
#define PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE (1 << 28)
|
||||
/*
|
||||
* ICL+ uses the same PLANE_CTL_FORMAT bits, but the field definition
|
||||
* expanded to include bit 23 as well. However, the shift-24 based values
|
||||
|
@ -6400,6 +6415,7 @@ enum {
|
|||
#define PLANE_CTL_KEY_ENABLE_DESTINATION ( 2 << 21)
|
||||
#define PLANE_CTL_ORDER_BGRX (0 << 20)
|
||||
#define PLANE_CTL_ORDER_RGBX (1 << 20)
|
||||
#define PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709 (1 << 18)
|
||||
#define PLANE_CTL_YUV422_ORDER_MASK (0x3 << 16)
|
||||
#define PLANE_CTL_YUV422_YUYV ( 0 << 16)
|
||||
#define PLANE_CTL_YUV422_UYVY ( 1 << 16)
|
||||
|
@ -6452,7 +6468,13 @@ enum {
|
|||
#define _PLANE_COLOR_CTL_2_A 0x702CC /* GLK+ */
|
||||
#define _PLANE_COLOR_CTL_3_A 0x703CC /* GLK+ */
|
||||
#define PLANE_COLOR_PIPE_GAMMA_ENABLE (1 << 30)
|
||||
#define PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE (1 << 28)
|
||||
#define PLANE_COLOR_PIPE_CSC_ENABLE (1 << 23)
|
||||
#define PLANE_COLOR_CSC_MODE_BYPASS (0 << 17)
|
||||
#define PLANE_COLOR_CSC_MODE_YUV601_TO_RGB709 (1 << 17)
|
||||
#define PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709 (2 << 17)
|
||||
#define PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020 (3 << 17)
|
||||
#define PLANE_COLOR_CSC_MODE_RGB709_TO_RGB2020 (4 << 17)
|
||||
#define PLANE_COLOR_PLANE_GAMMA_DISABLE (1 << 13)
|
||||
#define PLANE_COLOR_ALPHA_MASK (0x3 << 4)
|
||||
#define PLANE_COLOR_ALPHA_DISABLE (0 << 4)
|
||||
|
|
|
@ -3083,9 +3083,6 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
|
|||
|
||||
static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
|
||||
{
|
||||
struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
|
||||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
struct intel_crtc *crtc = to_intel_crtc(plane_state->base.crtc);
|
||||
const struct drm_framebuffer *fb = plane_state->base.fb;
|
||||
int src_x = plane_state->base.src.x1 >> 16;
|
||||
int src_y = plane_state->base.src.y1 >> 16;
|
||||
|
@ -3095,11 +3092,6 @@ static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
|
|||
int y = src_y / vsub;
|
||||
u32 offset;
|
||||
|
||||
if (!skl_plane_has_ccs(dev_priv, crtc->pipe, plane->id)) {
|
||||
DRM_DEBUG_KMS("No RC support on %s\n", plane->base.name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (plane_state->base.rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180)) {
|
||||
DRM_DEBUG_KMS("RC support only with 0/180 degree rotation %x\n",
|
||||
plane_state->base.rotation);
|
||||
|
@ -3564,6 +3556,12 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
|
|||
PLANE_CTL_PIPE_GAMMA_ENABLE |
|
||||
PLANE_CTL_PIPE_CSC_ENABLE |
|
||||
PLANE_CTL_PLANE_GAMMA_DISABLE;
|
||||
|
||||
if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
|
||||
plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709;
|
||||
|
||||
if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
|
||||
plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE;
|
||||
}
|
||||
|
||||
plane_ctl |= skl_plane_ctl_format(fb->format->format);
|
||||
|
@ -3593,6 +3591,16 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
|
|||
plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
|
||||
plane_color_ctl |= glk_plane_color_ctl_alpha(fb->format->format);
|
||||
|
||||
if (intel_format_is_yuv(fb->format->format)) {
|
||||
if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
|
||||
plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
|
||||
else
|
||||
plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV601_TO_RGB709;
|
||||
|
||||
if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
|
||||
plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
|
||||
}
|
||||
|
||||
return plane_color_ctl;
|
||||
}
|
||||
|
||||
|
@ -9389,18 +9397,12 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state,
|
|||
struct intel_plane_state *plane_state)
|
||||
{
|
||||
const struct drm_framebuffer *fb = plane_state->base.fb;
|
||||
struct drm_rect clip = {};
|
||||
int src_x, src_y;
|
||||
u32 offset;
|
||||
int ret;
|
||||
|
||||
if (crtc_state->base.enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->base.mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(&plane_state->base,
|
||||
&crtc_state->base,
|
||||
&clip,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
true, true);
|
||||
|
@ -12839,7 +12841,6 @@ intel_check_primary_plane(struct intel_plane *plane,
|
|||
int min_scale = DRM_PLANE_HELPER_NO_SCALING;
|
||||
int max_scale = DRM_PLANE_HELPER_NO_SCALING;
|
||||
bool can_position = false;
|
||||
struct drm_rect clip = {};
|
||||
int ret;
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 9) {
|
||||
|
@ -12851,13 +12852,8 @@ intel_check_primary_plane(struct intel_plane *plane,
|
|||
can_position = true;
|
||||
}
|
||||
|
||||
if (crtc_state->base.enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->base.mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(&state->base,
|
||||
&crtc_state->base,
|
||||
&clip,
|
||||
min_scale, max_scale,
|
||||
can_position, true);
|
||||
if (ret)
|
||||
|
@ -13338,6 +13334,15 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
|
|||
DRM_MODE_ROTATE_0,
|
||||
supported_rotations);
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 9)
|
||||
drm_plane_create_color_properties(&primary->base,
|
||||
BIT(DRM_COLOR_YCBCR_BT601) |
|
||||
BIT(DRM_COLOR_YCBCR_BT709),
|
||||
BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
|
||||
BIT(DRM_COLOR_YCBCR_FULL_RANGE),
|
||||
DRM_COLOR_YCBCR_BT709,
|
||||
DRM_COLOR_YCBCR_LIMITED_RANGE);
|
||||
|
||||
drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs);
|
||||
|
||||
return primary;
|
||||
|
|
|
@ -1596,6 +1596,7 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
|
|||
const struct intel_plane_state *plane_state);
|
||||
u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state);
|
||||
u32 glk_color_ctl(const struct intel_plane_state *plane_state);
|
||||
u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane,
|
||||
unsigned int rotation);
|
||||
int skl_check_plane_surface(const struct intel_crtc_state *crtc_state,
|
||||
|
@ -2021,6 +2022,7 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
|
|||
|
||||
|
||||
/* intel_sprite.c */
|
||||
bool intel_format_is_yuv(u32 format);
|
||||
int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
|
||||
int usecs);
|
||||
struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv,
|
||||
|
|
|
@ -41,8 +41,7 @@
|
|||
#include <drm/i915_drm.h>
|
||||
#include "i915_drv.h"
|
||||
|
||||
static bool
|
||||
format_is_yuv(uint32_t format)
|
||||
bool intel_format_is_yuv(u32 format)
|
||||
{
|
||||
switch (format) {
|
||||
case DRM_FORMAT_YUYV:
|
||||
|
@ -266,6 +265,7 @@ skl_update_plane(struct intel_plane *plane,
|
|||
if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
|
||||
I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id),
|
||||
plane_state->color_ctl);
|
||||
|
||||
if (key->flags) {
|
||||
I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
|
||||
I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), key->max_value);
|
||||
|
@ -346,44 +346,103 @@ skl_plane_get_hw_state(struct intel_plane *plane)
|
|||
}
|
||||
|
||||
static void
|
||||
chv_update_csc(struct intel_plane *plane, uint32_t format)
|
||||
chv_update_csc(const struct intel_plane_state *plane_state)
|
||||
{
|
||||
struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
|
||||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
const struct drm_framebuffer *fb = plane_state->base.fb;
|
||||
enum plane_id plane_id = plane->id;
|
||||
/*
|
||||
* |r| | c0 c1 c2 | |cr|
|
||||
* |g| = | c3 c4 c5 | x |y |
|
||||
* |b| | c6 c7 c8 | |cb|
|
||||
*
|
||||
* Coefficients are s3.12.
|
||||
*
|
||||
* Cb and Cr apparently come in as signed already, and
|
||||
* we always get full range data in on account of CLRC0/1.
|
||||
*/
|
||||
static const s16 csc_matrix[][9] = {
|
||||
/* BT.601 full range YCbCr -> full range RGB */
|
||||
[DRM_COLOR_YCBCR_BT601] = {
|
||||
5743, 4096, 0,
|
||||
-2925, 4096, -1410,
|
||||
0, 4096, 7258,
|
||||
},
|
||||
/* BT.709 full range YCbCr -> full range RGB */
|
||||
[DRM_COLOR_YCBCR_BT709] = {
|
||||
6450, 4096, 0,
|
||||
-1917, 4096, -767,
|
||||
0, 4096, 7601,
|
||||
},
|
||||
};
|
||||
const s16 *csc = csc_matrix[plane_state->base.color_encoding];
|
||||
|
||||
/* Seems RGB data bypasses the CSC always */
|
||||
if (!format_is_yuv(format))
|
||||
if (!intel_format_is_yuv(fb->format->format))
|
||||
return;
|
||||
|
||||
/*
|
||||
* BT.601 limited range YCbCr -> full range RGB
|
||||
*
|
||||
* |r| | 6537 4769 0| |cr |
|
||||
* |g| = |-3330 4769 -1605| x |y-64|
|
||||
* |b| | 0 4769 8263| |cb |
|
||||
*
|
||||
* Cb and Cr apparently come in as signed already, so no
|
||||
* need for any offset. For Y we need to remove the offset.
|
||||
*/
|
||||
I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(-64));
|
||||
I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
|
||||
I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
|
||||
I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
|
||||
|
||||
I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(4769) | SPCSC_C0(6537));
|
||||
I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(-3330) | SPCSC_C0(0));
|
||||
I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(-1605) | SPCSC_C0(4769));
|
||||
I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(4769) | SPCSC_C0(0));
|
||||
I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(8263));
|
||||
I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
|
||||
I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
|
||||
I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
|
||||
I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
|
||||
I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(csc[8]));
|
||||
|
||||
I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(940) | SPCSC_IMIN(64));
|
||||
I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
|
||||
I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
|
||||
I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(1023) | SPCSC_IMIN(0));
|
||||
I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
|
||||
I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
|
||||
|
||||
I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
|
||||
I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
|
||||
I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
|
||||
}
|
||||
|
||||
#define SIN_0 0
|
||||
#define COS_0 1
|
||||
|
||||
static void
|
||||
vlv_update_clrc(const struct intel_plane_state *plane_state)
|
||||
{
|
||||
struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
|
||||
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
|
||||
const struct drm_framebuffer *fb = plane_state->base.fb;
|
||||
enum pipe pipe = plane->pipe;
|
||||
enum plane_id plane_id = plane->id;
|
||||
int contrast, brightness, sh_scale, sh_sin, sh_cos;
|
||||
|
||||
if (intel_format_is_yuv(fb->format->format) &&
|
||||
plane_state->base.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
|
||||
/*
|
||||
* Expand limited range to full range:
|
||||
* Contrast is applied first and is used to expand Y range.
|
||||
* Brightness is applied second and is used to remove the
|
||||
* offset from Y. Saturation/hue is used to expand CbCr range.
|
||||
*/
|
||||
contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
|
||||
brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
|
||||
sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
|
||||
sh_sin = SIN_0 * sh_scale;
|
||||
sh_cos = COS_0 * sh_scale;
|
||||
} else {
|
||||
/* Pass-through everything. */
|
||||
contrast = 1 << 6;
|
||||
brightness = 0;
|
||||
sh_scale = 1 << 7;
|
||||
sh_sin = SIN_0 * sh_scale;
|
||||
sh_cos = COS_0 * sh_scale;
|
||||
}
|
||||
|
||||
/* FIXME these register are single buffered :( */
|
||||
I915_WRITE_FW(SPCLRC0(pipe, plane_id),
|
||||
SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
|
||||
I915_WRITE_FW(SPCLRC1(pipe, plane_id),
|
||||
SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
|
||||
}
|
||||
|
||||
static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state)
|
||||
{
|
||||
|
@ -433,6 +492,9 @@ static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
|
||||
sprctl |= SP_YUV_FORMAT_BT709;
|
||||
|
||||
if (fb->modifier == I915_FORMAT_MOD_X_TILED)
|
||||
sprctl |= SP_TILED;
|
||||
|
||||
|
@ -477,8 +539,10 @@ vlv_update_plane(struct intel_plane *plane,
|
|||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
vlv_update_clrc(plane_state);
|
||||
|
||||
if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
|
||||
chv_update_csc(plane, fb->format->format);
|
||||
chv_update_csc(plane_state);
|
||||
|
||||
if (key->flags) {
|
||||
I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value);
|
||||
|
@ -584,6 +648,12 @@ static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
|
||||
sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
|
||||
|
||||
if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
|
||||
sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
|
||||
|
||||
if (fb->modifier == I915_FORMAT_MOD_X_TILED)
|
||||
sprctl |= SPRITE_TILED;
|
||||
|
||||
|
@ -740,6 +810,12 @@ static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
|
||||
dvscntr |= DVS_YUV_FORMAT_BT709;
|
||||
|
||||
if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
|
||||
dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
|
||||
|
||||
if (fb->modifier == I915_FORMAT_MOD_X_TILED)
|
||||
dvscntr |= DVS_TILED;
|
||||
|
||||
|
@ -979,7 +1055,7 @@ intel_check_sprite_plane(struct intel_plane *plane,
|
|||
src_y = src->y1 >> 16;
|
||||
src_h = drm_rect_height(src) >> 16;
|
||||
|
||||
if (format_is_yuv(fb->format->format)) {
|
||||
if (intel_format_is_yuv(fb->format->format)) {
|
||||
src_x &= ~1;
|
||||
src_w &= ~1;
|
||||
|
||||
|
@ -1459,6 +1535,14 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
|
|||
DRM_MODE_ROTATE_0,
|
||||
supported_rotations);
|
||||
|
||||
drm_plane_create_color_properties(&intel_plane->base,
|
||||
BIT(DRM_COLOR_YCBCR_BT601) |
|
||||
BIT(DRM_COLOR_YCBCR_BT709),
|
||||
BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
|
||||
BIT(DRM_COLOR_YCBCR_FULL_RANGE),
|
||||
DRM_COLOR_YCBCR_BT709,
|
||||
DRM_COLOR_YCBCR_LIMITED_RANGE);
|
||||
|
||||
drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
|
||||
|
||||
return intel_plane;
|
||||
|
|
|
@ -351,7 +351,6 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
|
|||
struct drm_framebuffer *old_fb = old_state->fb;
|
||||
unsigned long eba, ubo, vbo, old_ubo, old_vbo, alpha_eba;
|
||||
bool can_position = (plane->type == DRM_PLANE_TYPE_OVERLAY);
|
||||
struct drm_rect clip = {};
|
||||
int hsub, vsub;
|
||||
int ret;
|
||||
|
||||
|
@ -367,11 +366,7 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
|
|||
if (WARN_ON(!crtc_state))
|
||||
return -EINVAL;
|
||||
|
||||
if (crtc_state->enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
|
||||
ret = drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
can_position, true);
|
||||
|
|
|
@ -91,7 +91,6 @@ static int mtk_plane_atomic_check(struct drm_plane *plane,
|
|||
{
|
||||
struct drm_framebuffer *fb = state->fb;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_rect clip = { 0, };
|
||||
|
||||
if (!fb)
|
||||
return 0;
|
||||
|
@ -108,11 +107,7 @@ static int mtk_plane_atomic_check(struct drm_plane *plane,
|
|||
if (IS_ERR(crtc_state))
|
||||
return PTR_ERR(crtc_state);
|
||||
|
||||
if (crtc_state->enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
return drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
|
||||
return drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
true, true);
|
||||
|
|
|
@ -49,7 +49,6 @@ static int meson_plane_atomic_check(struct drm_plane *plane,
|
|||
struct drm_plane_state *state)
|
||||
{
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_rect clip = { 0, };
|
||||
|
||||
if (!state->crtc)
|
||||
return 0;
|
||||
|
@ -58,11 +57,7 @@ static int meson_plane_atomic_check(struct drm_plane *plane,
|
|||
if (IS_ERR(crtc_state))
|
||||
return PTR_ERR(crtc_state);
|
||||
|
||||
if (crtc_state->enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
return drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
|
||||
return drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
true, true);
|
||||
|
|
|
@ -286,7 +286,6 @@ static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state,
|
|||
uint32_t max_width, max_height;
|
||||
bool out_of_bounds = false;
|
||||
uint32_t caps = 0;
|
||||
struct drm_rect clip = {};
|
||||
int min_scale, max_scale;
|
||||
int ret;
|
||||
|
||||
|
@ -323,11 +322,7 @@ static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state,
|
|||
min_scale = FRAC_16_16(1, 8);
|
||||
max_scale = FRAC_16_16(8, 1);
|
||||
|
||||
if (crtc_state->enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
|
||||
ret = drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
min_scale, max_scale,
|
||||
true, true);
|
||||
if (ret)
|
||||
|
@ -471,7 +466,6 @@ static int mdp5_plane_atomic_async_check(struct drm_plane *plane,
|
|||
{
|
||||
struct mdp5_plane_state *mdp5_state = to_mdp5_plane_state(state);
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_rect clip = {};
|
||||
int min_scale, max_scale;
|
||||
int ret;
|
||||
|
||||
|
@ -502,11 +496,7 @@ static int mdp5_plane_atomic_async_check(struct drm_plane *plane,
|
|||
min_scale = FRAC_16_16(1, 8);
|
||||
max_scale = FRAC_16_16(8, 1);
|
||||
|
||||
if (crtc_state->enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
|
||||
ret = drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
min_scale, max_scale,
|
||||
true, true);
|
||||
if (ret)
|
||||
|
|
|
@ -131,11 +131,37 @@ static int mxsfb_pipe_prepare_fb(struct drm_simple_display_pipe *pipe,
|
|||
return drm_gem_fb_prepare_fb(&pipe->plane, plane_state);
|
||||
}
|
||||
|
||||
static int mxsfb_pipe_enable_vblank(struct drm_simple_display_pipe *pipe)
|
||||
{
|
||||
struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
|
||||
|
||||
/* Clear and enable VBLANK IRQ */
|
||||
mxsfb_enable_axi_clk(mxsfb);
|
||||
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
|
||||
writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
|
||||
mxsfb_disable_axi_clk(mxsfb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mxsfb_pipe_disable_vblank(struct drm_simple_display_pipe *pipe)
|
||||
{
|
||||
struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
|
||||
|
||||
/* Disable and clear VBLANK IRQ */
|
||||
mxsfb_enable_axi_clk(mxsfb);
|
||||
writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
|
||||
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
|
||||
mxsfb_disable_axi_clk(mxsfb);
|
||||
}
|
||||
|
||||
static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
|
||||
.enable = mxsfb_pipe_enable,
|
||||
.disable = mxsfb_pipe_disable,
|
||||
.update = mxsfb_pipe_update,
|
||||
.prepare_fb = mxsfb_pipe_prepare_fb,
|
||||
.enable_vblank = mxsfb_pipe_enable_vblank,
|
||||
.disable_vblank = mxsfb_pipe_disable_vblank,
|
||||
};
|
||||
|
||||
static int mxsfb_load(struct drm_device *drm, unsigned long flags)
|
||||
|
@ -274,33 +300,11 @@ static void mxsfb_lastclose(struct drm_device *drm)
|
|||
drm_fbdev_cma_restore_mode(mxsfb->fbdev);
|
||||
}
|
||||
|
||||
static int mxsfb_enable_vblank(struct drm_device *drm, unsigned int crtc)
|
||||
{
|
||||
struct mxsfb_drm_private *mxsfb = drm->dev_private;
|
||||
|
||||
/* Clear and enable VBLANK IRQ */
|
||||
mxsfb_enable_axi_clk(mxsfb);
|
||||
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
|
||||
writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
|
||||
mxsfb_disable_axi_clk(mxsfb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mxsfb_disable_vblank(struct drm_device *drm, unsigned int crtc)
|
||||
{
|
||||
struct mxsfb_drm_private *mxsfb = drm->dev_private;
|
||||
|
||||
/* Disable and clear VBLANK IRQ */
|
||||
mxsfb_enable_axi_clk(mxsfb);
|
||||
writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
|
||||
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
|
||||
mxsfb_disable_axi_clk(mxsfb);
|
||||
}
|
||||
|
||||
static void mxsfb_irq_preinstall(struct drm_device *drm)
|
||||
{
|
||||
mxsfb_disable_vblank(drm, 0);
|
||||
struct mxsfb_drm_private *mxsfb = drm->dev_private;
|
||||
|
||||
mxsfb_pipe_disable_vblank(&mxsfb->pipe);
|
||||
}
|
||||
|
||||
static irqreturn_t mxsfb_irq_handler(int irq, void *data)
|
||||
|
@ -333,8 +337,6 @@ static struct drm_driver mxsfb_driver = {
|
|||
.irq_handler = mxsfb_irq_handler,
|
||||
.irq_preinstall = mxsfb_irq_preinstall,
|
||||
.irq_uninstall = mxsfb_irq_preinstall,
|
||||
.enable_vblank = mxsfb_enable_vblank,
|
||||
.disable_vblank = mxsfb_disable_vblank,
|
||||
.gem_free_object_unlocked = drm_gem_cma_free_object,
|
||||
.gem_vm_ops = &drm_gem_cma_vm_ops,
|
||||
.dumb_create = drm_gem_cma_dumb_create,
|
||||
|
|
|
@ -46,7 +46,6 @@ struct nouveau_plane {
|
|||
struct drm_property *brightness;
|
||||
struct drm_property *hue;
|
||||
struct drm_property *saturation;
|
||||
struct drm_property *iturbt_709;
|
||||
} props;
|
||||
|
||||
int colorkey;
|
||||
|
@ -54,7 +53,7 @@ struct nouveau_plane {
|
|||
int brightness;
|
||||
int hue;
|
||||
int saturation;
|
||||
int iturbt_709;
|
||||
enum drm_color_encoding color_encoding;
|
||||
|
||||
void (*set_params)(struct nouveau_plane *);
|
||||
};
|
||||
|
@ -166,7 +165,7 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
if (fb->format->format == DRM_FORMAT_NV12 ||
|
||||
fb->format->format == DRM_FORMAT_NV21)
|
||||
format |= NV_PVIDEO_FORMAT_PLANAR;
|
||||
if (nv_plane->iturbt_709)
|
||||
if (nv_plane->color_encoding == DRM_COLOR_YCBCR_BT709)
|
||||
format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
|
||||
if (nv_plane->colorkey & (1 << 24))
|
||||
format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;
|
||||
|
@ -229,7 +228,7 @@ nv10_set_params(struct nouveau_plane *plane)
|
|||
nvif_wr32(dev, NV_PVIDEO_COLOR_KEY, plane->colorkey & 0xffffff);
|
||||
|
||||
if (plane->cur) {
|
||||
if (plane->iturbt_709)
|
||||
if (plane->color_encoding == DRM_COLOR_YCBCR_BT709)
|
||||
format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709;
|
||||
if (plane->colorkey & (1 << 24))
|
||||
format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY;
|
||||
|
@ -258,8 +257,8 @@ nv_set_property(struct drm_plane *plane,
|
|||
nv_plane->hue = value;
|
||||
else if (property == nv_plane->props.saturation)
|
||||
nv_plane->saturation = value;
|
||||
else if (property == nv_plane->props.iturbt_709)
|
||||
nv_plane->iturbt_709 = value;
|
||||
else if (property == nv_plane->base.color_encoding_property)
|
||||
nv_plane->color_encoding = value;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -313,14 +312,11 @@ nv10_overlay_init(struct drm_device *device)
|
|||
device, 0, "hue", 0, 359);
|
||||
plane->props.saturation = drm_property_create_range(
|
||||
device, 0, "saturation", 0, 8192 - 1);
|
||||
plane->props.iturbt_709 = drm_property_create_range(
|
||||
device, 0, "iturbt_709", 0, 1);
|
||||
if (!plane->props.colorkey ||
|
||||
!plane->props.contrast ||
|
||||
!plane->props.brightness ||
|
||||
!plane->props.hue ||
|
||||
!plane->props.saturation ||
|
||||
!plane->props.iturbt_709)
|
||||
!plane->props.saturation)
|
||||
goto cleanup;
|
||||
|
||||
plane->colorkey = 0;
|
||||
|
@ -343,9 +339,13 @@ nv10_overlay_init(struct drm_device *device)
|
|||
drm_object_attach_property(&plane->base.base,
|
||||
plane->props.saturation, plane->saturation);
|
||||
|
||||
plane->iturbt_709 = 0;
|
||||
drm_object_attach_property(&plane->base.base,
|
||||
plane->props.iturbt_709, plane->iturbt_709);
|
||||
plane->color_encoding = DRM_COLOR_YCBCR_BT601;
|
||||
drm_plane_create_color_properties(&plane->base,
|
||||
BIT(DRM_COLOR_YCBCR_BT601) |
|
||||
BIT(DRM_COLOR_YCBCR_BT709),
|
||||
BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
|
||||
DRM_COLOR_YCBCR_BT601,
|
||||
DRM_COLOR_YCBCR_LIMITED_RANGE);
|
||||
|
||||
plane->set_params = nv10_set_params;
|
||||
nv10_set_params(plane);
|
||||
|
|
|
@ -1143,15 +1143,9 @@ static int
|
|||
nv50_curs_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
|
||||
struct nv50_head_atom *asyh)
|
||||
{
|
||||
struct drm_rect clip = {};
|
||||
int ret;
|
||||
|
||||
if (asyh->state.enable)
|
||||
drm_mode_get_hv_timing(&asyh->state.mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
|
||||
&clip,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
true, true);
|
||||
|
@ -1435,18 +1429,12 @@ nv50_base_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
|
|||
struct nv50_head_atom *asyh)
|
||||
{
|
||||
const struct drm_framebuffer *fb = asyw->state.fb;
|
||||
struct drm_rect clip = {};
|
||||
int ret;
|
||||
|
||||
if (!fb->format->depth)
|
||||
return -EINVAL;
|
||||
|
||||
if (asyh->state.enable)
|
||||
drm_mode_get_hv_timing(&asyh->state.mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
|
||||
&clip,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
false, true);
|
||||
|
|
|
@ -132,7 +132,7 @@ static const struct versatile_panel_type versatile_panels[] = {
|
|||
.width_mm = 79,
|
||||
.height_mm = 54,
|
||||
.mode = {
|
||||
.clock = 10000000,
|
||||
.clock = 10000,
|
||||
.hdisplay = 320,
|
||||
.hsync_start = 320 + 6,
|
||||
.hsync_end = 320 + 6 + 6,
|
||||
|
@ -156,7 +156,7 @@ static const struct versatile_panel_type versatile_panels[] = {
|
|||
.width_mm = 171,
|
||||
.height_mm = 130,
|
||||
.mode = {
|
||||
.clock = 25000000,
|
||||
.clock = 25000,
|
||||
.hdisplay = 640,
|
||||
.hsync_start = 640 + 24,
|
||||
.hsync_end = 640 + 24 + 96,
|
||||
|
@ -179,7 +179,7 @@ static const struct versatile_panel_type versatile_panels[] = {
|
|||
.width_mm = 34,
|
||||
.height_mm = 45,
|
||||
.mode = {
|
||||
.clock = 625000000,
|
||||
.clock = 62500,
|
||||
.hdisplay = 176,
|
||||
.hsync_start = 176 + 2,
|
||||
.hsync_end = 176 + 2 + 3,
|
||||
|
@ -203,7 +203,7 @@ static const struct versatile_panel_type versatile_panels[] = {
|
|||
.width_mm = 37,
|
||||
.height_mm = 50,
|
||||
.mode = {
|
||||
.clock = 5400000,
|
||||
.clock = 5400,
|
||||
.hdisplay = 240,
|
||||
.hsync_start = 240 + 10,
|
||||
.hsync_end = 240 + 10 + 10,
|
||||
|
|
|
@ -8,7 +8,6 @@ config DRM_PL111
|
|||
select DRM_GEM_CMA_HELPER
|
||||
select DRM_BRIDGE
|
||||
select DRM_PANEL_BRIDGE
|
||||
select DRM_DUMB_VGA_DAC
|
||||
select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
|
||||
help
|
||||
Choose this option for DRM support for the PL111 CLCD controller.
|
||||
|
|
|
@ -50,6 +50,41 @@ irqreturn_t pl111_irq(int irq, void *data)
|
|||
return status;
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
pl111_mode_valid(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_device *drm = crtc->dev;
|
||||
struct pl111_drm_dev_private *priv = drm->dev_private;
|
||||
u32 cpp = priv->variant->fb_bpp / 8;
|
||||
u64 bw;
|
||||
|
||||
/*
|
||||
* We use the pixelclock to also account for interlaced modes, the
|
||||
* resulting bandwidth is in bytes per second.
|
||||
*/
|
||||
bw = mode->clock * 1000; /* In Hz */
|
||||
bw = bw * mode->hdisplay * mode->vdisplay * cpp;
|
||||
bw = div_u64(bw, mode->htotal * mode->vtotal);
|
||||
|
||||
/*
|
||||
* If no bandwidth constraints, anything goes, else
|
||||
* check if we are too fast.
|
||||
*/
|
||||
if (priv->memory_bw && (bw > priv->memory_bw)) {
|
||||
DRM_DEBUG_KMS("%d x %d @ %d Hz, %d cpp, bw %llu too fast\n",
|
||||
mode->hdisplay, mode->vdisplay,
|
||||
mode->clock * 1000, cpp, bw);
|
||||
|
||||
return MODE_BAD;
|
||||
}
|
||||
DRM_DEBUG_KMS("%d x %d @ %d Hz, %d cpp, bw %llu bytes/s OK\n",
|
||||
mode->hdisplay, mode->vdisplay,
|
||||
mode->clock * 1000, cpp, bw);
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static int pl111_display_check(struct drm_simple_display_pipe *pipe,
|
||||
struct drm_plane_state *pstate,
|
||||
struct drm_crtc_state *cstate)
|
||||
|
@ -321,8 +356,10 @@ static void pl111_display_update(struct drm_simple_display_pipe *pipe,
|
|||
}
|
||||
}
|
||||
|
||||
int pl111_enable_vblank(struct drm_device *drm, unsigned int crtc)
|
||||
static int pl111_display_enable_vblank(struct drm_simple_display_pipe *pipe)
|
||||
{
|
||||
struct drm_crtc *crtc = &pipe->crtc;
|
||||
struct drm_device *drm = crtc->dev;
|
||||
struct pl111_drm_dev_private *priv = drm->dev_private;
|
||||
|
||||
writel(CLCD_IRQ_NEXTBASE_UPDATE, priv->regs + priv->ienb);
|
||||
|
@ -330,8 +367,10 @@ int pl111_enable_vblank(struct drm_device *drm, unsigned int crtc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void pl111_disable_vblank(struct drm_device *drm, unsigned int crtc)
|
||||
static void pl111_display_disable_vblank(struct drm_simple_display_pipe *pipe)
|
||||
{
|
||||
struct drm_crtc *crtc = &pipe->crtc;
|
||||
struct drm_device *drm = crtc->dev;
|
||||
struct pl111_drm_dev_private *priv = drm->dev_private;
|
||||
|
||||
writel(0, priv->regs + priv->ienb);
|
||||
|
@ -343,7 +382,8 @@ static int pl111_display_prepare_fb(struct drm_simple_display_pipe *pipe,
|
|||
return drm_gem_fb_prepare_fb(&pipe->plane, plane_state);
|
||||
}
|
||||
|
||||
static const struct drm_simple_display_pipe_funcs pl111_display_funcs = {
|
||||
static struct drm_simple_display_pipe_funcs pl111_display_funcs = {
|
||||
.mode_valid = pl111_mode_valid,
|
||||
.check = pl111_display_check,
|
||||
.enable = pl111_display_enable,
|
||||
.disable = pl111_display_disable,
|
||||
|
@ -502,6 +542,11 @@ int pl111_display_init(struct drm_device *drm)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!priv->variant->broken_vblank) {
|
||||
pl111_display_funcs.enable_vblank = pl111_display_enable_vblank;
|
||||
pl111_display_funcs.disable_vblank = pl111_display_disable_vblank;
|
||||
}
|
||||
|
||||
ret = drm_simple_display_pipe_init(drm, &priv->pipe,
|
||||
&pl111_display_funcs,
|
||||
priv->variant->formats,
|
||||
|
|
|
@ -43,6 +43,7 @@ struct drm_minor;
|
|||
* @broken_vblank: the vblank IRQ is broken on this variant
|
||||
* @formats: array of supported pixel formats on this variant
|
||||
* @nformats: the length of the array of supported pixel formats
|
||||
* @fb_bpp: desired bits per pixel on the default framebuffer
|
||||
*/
|
||||
struct pl111_variant_data {
|
||||
const char *name;
|
||||
|
@ -52,6 +53,7 @@ struct pl111_variant_data {
|
|||
bool broken_vblank;
|
||||
const u32 *formats;
|
||||
unsigned int nformats;
|
||||
unsigned int fb_bpp;
|
||||
};
|
||||
|
||||
struct pl111_drm_dev_private {
|
||||
|
@ -63,6 +65,7 @@ struct pl111_drm_dev_private {
|
|||
struct drm_simple_display_pipe pipe;
|
||||
|
||||
void *regs;
|
||||
u32 memory_bw;
|
||||
u32 ienb;
|
||||
u32 ctrl;
|
||||
/* The pixel clock (a reference to our clock divider off of CLCDCLK). */
|
||||
|
@ -79,8 +82,6 @@ struct pl111_drm_dev_private {
|
|||
};
|
||||
|
||||
int pl111_display_init(struct drm_device *dev);
|
||||
int pl111_enable_vblank(struct drm_device *drm, unsigned int crtc);
|
||||
void pl111_disable_vblank(struct drm_device *drm, unsigned int crtc);
|
||||
irqreturn_t pl111_irq(int irq, void *data);
|
||||
int pl111_debugfs_init(struct drm_minor *minor);
|
||||
|
||||
|
|
|
@ -192,7 +192,7 @@ static int pl111_modeset_init(struct drm_device *dev)
|
|||
|
||||
drm_mode_config_reset(dev);
|
||||
|
||||
drm_fb_cma_fbdev_init(dev, 32, 0);
|
||||
drm_fb_cma_fbdev_init(dev, priv->variant->fb_bpp, 0);
|
||||
|
||||
drm_kms_helper_poll_init(dev);
|
||||
|
||||
|
@ -249,11 +249,6 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
|
|||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!variant->broken_vblank) {
|
||||
pl111_drm_driver.enable_vblank = pl111_enable_vblank;
|
||||
pl111_drm_driver.disable_vblank = pl111_disable_vblank;
|
||||
}
|
||||
|
||||
drm = drm_dev_alloc(&pl111_drm_driver, dev);
|
||||
if (IS_ERR(drm))
|
||||
return PTR_ERR(drm);
|
||||
|
@ -262,6 +257,12 @@ static int pl111_amba_probe(struct amba_device *amba_dev,
|
|||
drm->dev_private = priv;
|
||||
priv->variant = variant;
|
||||
|
||||
if (of_property_read_u32(dev->of_node, "max-memory-bandwidth",
|
||||
&priv->memory_bw)) {
|
||||
dev_info(dev, "no max memory bandwidth specified, assume unlimited\n");
|
||||
priv->memory_bw = 0;
|
||||
}
|
||||
|
||||
/* The two variants swap this register */
|
||||
if (variant->is_pl110) {
|
||||
priv->ienb = CLCD_PL110_IENB;
|
||||
|
@ -341,6 +342,7 @@ static const struct pl111_variant_data pl110_variant = {
|
|||
.is_pl110 = true,
|
||||
.formats = pl110_pixel_formats,
|
||||
.nformats = ARRAY_SIZE(pl110_pixel_formats),
|
||||
.fb_bpp = 16,
|
||||
};
|
||||
|
||||
/* RealView, Versatile Express etc use this modern variant */
|
||||
|
@ -365,6 +367,7 @@ static const struct pl111_variant_data pl111_variant = {
|
|||
.name = "PL111",
|
||||
.formats = pl111_pixel_formats,
|
||||
.nformats = ARRAY_SIZE(pl111_pixel_formats),
|
||||
.fb_bpp = 32,
|
||||
};
|
||||
|
||||
static const struct amba_id pl111_id_table[] = {
|
||||
|
|
|
@ -230,6 +230,23 @@ static const u32 pl110_versatile_pixel_formats[] = {
|
|||
DRM_FORMAT_XRGB1555,
|
||||
};
|
||||
|
||||
static const u32 pl111_realview_pixel_formats[] = {
|
||||
DRM_FORMAT_ABGR8888,
|
||||
DRM_FORMAT_XBGR8888,
|
||||
DRM_FORMAT_ARGB8888,
|
||||
DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_BGR565,
|
||||
DRM_FORMAT_RGB565,
|
||||
DRM_FORMAT_ABGR1555,
|
||||
DRM_FORMAT_XBGR1555,
|
||||
DRM_FORMAT_ARGB1555,
|
||||
DRM_FORMAT_XRGB1555,
|
||||
DRM_FORMAT_ABGR4444,
|
||||
DRM_FORMAT_XBGR4444,
|
||||
DRM_FORMAT_ARGB4444,
|
||||
DRM_FORMAT_XRGB4444,
|
||||
};
|
||||
|
||||
/*
|
||||
* The Integrator variant is a PL110 with a bunch of broken, or not
|
||||
* yet implemented features
|
||||
|
@ -241,6 +258,7 @@ static const struct pl111_variant_data pl110_integrator = {
|
|||
.broken_vblank = true,
|
||||
.formats = pl110_integrator_pixel_formats,
|
||||
.nformats = ARRAY_SIZE(pl110_integrator_pixel_formats),
|
||||
.fb_bpp = 16,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -253,6 +271,19 @@ static const struct pl111_variant_data pl110_versatile = {
|
|||
.external_bgr = true,
|
||||
.formats = pl110_versatile_pixel_formats,
|
||||
.nformats = ARRAY_SIZE(pl110_versatile_pixel_formats),
|
||||
.fb_bpp = 16,
|
||||
};
|
||||
|
||||
/*
|
||||
* RealView PL111 variant, the only real difference from the vanilla
|
||||
* PL111 is that we select 16bpp framebuffer by default to be able
|
||||
* to get 1024x768 without saturating the memory bus.
|
||||
*/
|
||||
static const struct pl111_variant_data pl111_realview = {
|
||||
.name = "PL111 RealView",
|
||||
.formats = pl111_realview_pixel_formats,
|
||||
.nformats = ARRAY_SIZE(pl111_realview_pixel_formats),
|
||||
.fb_bpp = 16,
|
||||
};
|
||||
|
||||
int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv)
|
||||
|
@ -304,6 +335,7 @@ int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv)
|
|||
case REALVIEW_CLCD_PBA8:
|
||||
case REALVIEW_CLCD_PBX:
|
||||
versatile_syscon_map = map;
|
||||
priv->variant = &pl111_realview;
|
||||
priv->variant_display_enable = pl111_realview_clcd_enable;
|
||||
priv->variant_display_disable = pl111_realview_clcd_disable;
|
||||
dev_info(dev, "set up callbacks for RealView PL111\n");
|
||||
|
|
|
@ -572,7 +572,6 @@ int __rcar_du_plane_atomic_check(struct drm_plane *plane,
|
|||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_rect clip = {};
|
||||
int ret;
|
||||
|
||||
if (!state->crtc) {
|
||||
|
@ -589,11 +588,7 @@ int __rcar_du_plane_atomic_check(struct drm_plane *plane,
|
|||
if (IS_ERR(crtc_state))
|
||||
return PTR_ERR(crtc_state);
|
||||
|
||||
if (crtc_state->enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
|
||||
ret = drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
true, true);
|
||||
|
|
|
@ -77,6 +77,7 @@ struct rockchip_dp_device {
|
|||
|
||||
const struct rockchip_dp_chip_data *data;
|
||||
|
||||
struct analogix_dp_device *adp;
|
||||
struct analogix_dp_plat_data plat_data;
|
||||
};
|
||||
|
||||
|
@ -84,7 +85,7 @@ static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
|
|||
{
|
||||
struct rockchip_dp_device *dp = to_dp(encoder);
|
||||
|
||||
if (!analogix_dp_psr_supported(dp->dev))
|
||||
if (!analogix_dp_psr_supported(dp->adp))
|
||||
return;
|
||||
|
||||
DRM_DEV_DEBUG(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit");
|
||||
|
@ -114,9 +115,9 @@ static void analogix_dp_psr_work(struct work_struct *work)
|
|||
|
||||
mutex_lock(&dp->psr_lock);
|
||||
if (dp->psr_state == EDP_VSC_PSR_STATE_ACTIVE)
|
||||
analogix_dp_enable_psr(dp->dev);
|
||||
analogix_dp_enable_psr(dp->adp);
|
||||
else
|
||||
analogix_dp_disable_psr(dp->dev);
|
||||
analogix_dp_disable_psr(dp->adp);
|
||||
mutex_unlock(&dp->psr_lock);
|
||||
}
|
||||
|
||||
|
@ -149,12 +150,17 @@ static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data)
|
|||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return rockchip_drm_psr_activate(&dp->encoder);
|
||||
}
|
||||
|
||||
static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data)
|
||||
{
|
||||
struct rockchip_dp_device *dp = to_dp(plat_data);
|
||||
int ret;
|
||||
|
||||
ret = rockchip_drm_psr_deactivate(&dp->encoder);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
clk_disable_unprepare(dp->pclk);
|
||||
|
||||
|
@ -258,13 +264,8 @@ static struct drm_encoder_helper_funcs rockchip_dp_encoder_helper_funcs = {
|
|||
.atomic_check = rockchip_dp_drm_encoder_atomic_check,
|
||||
};
|
||||
|
||||
static void rockchip_dp_drm_encoder_destroy(struct drm_encoder *encoder)
|
||||
{
|
||||
drm_encoder_cleanup(encoder);
|
||||
}
|
||||
|
||||
static struct drm_encoder_funcs rockchip_dp_encoder_funcs = {
|
||||
.destroy = rockchip_dp_drm_encoder_destroy,
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
static int rockchip_dp_of_probe(struct rockchip_dp_device *dp)
|
||||
|
@ -334,13 +335,6 @@ static int rockchip_dp_bind(struct device *dev, struct device *master,
|
|||
struct drm_device *drm_dev = data;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Just like the probe function said, we don't need the
|
||||
* device drvrate anymore, we should leave the charge to
|
||||
* analogix dp driver, set the device drvdata to NULL.
|
||||
*/
|
||||
dev_set_drvdata(dev, NULL);
|
||||
|
||||
dp_data = of_device_get_match_data(dev);
|
||||
if (!dp_data)
|
||||
return -ENODEV;
|
||||
|
@ -365,9 +359,22 @@ static int rockchip_dp_bind(struct device *dev, struct device *master,
|
|||
dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE;
|
||||
INIT_WORK(&dp->psr_work, analogix_dp_psr_work);
|
||||
|
||||
rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set);
|
||||
ret = rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set);
|
||||
if (ret < 0)
|
||||
goto err_cleanup_encoder;
|
||||
|
||||
return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
|
||||
dp->adp = analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
|
||||
if (IS_ERR(dp->adp)) {
|
||||
ret = PTR_ERR(dp->adp);
|
||||
goto err_unreg_psr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_unreg_psr:
|
||||
rockchip_drm_psr_unregister(&dp->encoder);
|
||||
err_cleanup_encoder:
|
||||
dp->encoder.funcs->destroy(&dp->encoder);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rockchip_dp_unbind(struct device *dev, struct device *master,
|
||||
|
@ -375,9 +382,9 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master,
|
|||
{
|
||||
struct rockchip_dp_device *dp = dev_get_drvdata(dev);
|
||||
|
||||
analogix_dp_unbind(dp->adp);
|
||||
rockchip_drm_psr_unregister(&dp->encoder);
|
||||
|
||||
analogix_dp_unbind(dev, master, data);
|
||||
dp->encoder.funcs->destroy(&dp->encoder);
|
||||
}
|
||||
|
||||
static const struct component_ops rockchip_dp_component_ops = {
|
||||
|
@ -407,11 +414,6 @@ static int rockchip_dp_probe(struct platform_device *pdev)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* We just use the drvdata until driver run into component
|
||||
* add function, and then we would set drvdata to null, so
|
||||
* that analogix dp driver could take charge of the drvdata.
|
||||
*/
|
||||
platform_set_drvdata(pdev, dp);
|
||||
|
||||
return component_add(dev, &rockchip_dp_component_ops);
|
||||
|
@ -424,10 +426,26 @@ static int rockchip_dp_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int rockchip_dp_suspend(struct device *dev)
|
||||
{
|
||||
struct rockchip_dp_device *dp = dev_get_drvdata(dev);
|
||||
|
||||
return analogix_dp_suspend(dp->adp);
|
||||
}
|
||||
|
||||
static int rockchip_dp_resume(struct device *dev)
|
||||
{
|
||||
struct rockchip_dp_device *dp = dev_get_drvdata(dev);
|
||||
|
||||
return analogix_dp_resume(dp->adp);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops rockchip_dp_pm_ops = {
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.suspend = analogix_dp_suspend,
|
||||
.resume_early = analogix_dp_resume,
|
||||
.suspend = rockchip_dp_suspend,
|
||||
.resume_early = rockchip_dp_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -1302,8 +1302,8 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
|
|||
err_mipi_dsi_host:
|
||||
mipi_dsi_host_unregister(&dsi->dsi_host);
|
||||
err_cleanup:
|
||||
drm_encoder_cleanup(&dsi->encoder);
|
||||
drm_connector_cleanup(&dsi->connector);
|
||||
dsi->connector.funcs->destroy(&dsi->connector);
|
||||
dsi->encoder.funcs->destroy(&dsi->encoder);
|
||||
err_pllref:
|
||||
clk_disable_unprepare(dsi->pllref_clk);
|
||||
return ret;
|
||||
|
@ -1316,6 +1316,10 @@ static void dw_mipi_dsi_unbind(struct device *dev, struct device *master,
|
|||
|
||||
mipi_dsi_host_unregister(&dsi->dsi_host);
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
dsi->connector.funcs->destroy(&dsi->connector);
|
||||
dsi->encoder.funcs->destroy(&dsi->encoder);
|
||||
|
||||
clk_disable_unprepare(dsi->pllref_clk);
|
||||
}
|
||||
|
||||
|
|
|
@ -165,7 +165,6 @@ static const struct dw_hdmi_phy_config rockchip_phy_config[] = {
|
|||
static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
|
||||
{
|
||||
struct device_node *np = hdmi->dev->of_node;
|
||||
int ret;
|
||||
|
||||
hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
|
||||
if (IS_ERR(hdmi->regmap)) {
|
||||
|
@ -193,13 +192,6 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
|
|||
return PTR_ERR(hdmi->grf_clk);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(hdmi->vpll_clk);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(hdmi->dev,
|
||||
"Failed to enable HDMI vpll: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -374,6 +366,13 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(hdmi->vpll_clk);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
|
||||
drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
|
@ -389,6 +388,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
|||
if (IS_ERR(hdmi->hdmi)) {
|
||||
ret = PTR_ERR(hdmi->hdmi);
|
||||
drm_encoder_cleanup(encoder);
|
||||
clk_disable_unprepare(hdmi->vpll_clk);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -400,6 +400,7 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
|
|||
struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
|
||||
|
||||
dw_hdmi_unbind(hdmi->hdmi);
|
||||
clk_disable_unprepare(hdmi->vpll_clk);
|
||||
}
|
||||
|
||||
static const struct component_ops dw_hdmi_rockchip_ops = {
|
||||
|
|
|
@ -849,8 +849,10 @@ static int inno_hdmi_bind(struct device *dev, struct device *master,
|
|||
}
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
if (irq < 0) {
|
||||
ret = irq;
|
||||
goto err_disable_clk;
|
||||
}
|
||||
|
||||
inno_hdmi_reset(hdmi);
|
||||
|
||||
|
@ -858,7 +860,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master,
|
|||
if (IS_ERR(hdmi->ddc)) {
|
||||
ret = PTR_ERR(hdmi->ddc);
|
||||
hdmi->ddc = NULL;
|
||||
return ret;
|
||||
goto err_disable_clk;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -872,7 +874,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master,
|
|||
|
||||
ret = inno_hdmi_register(drm, hdmi);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_put_adapter;
|
||||
|
||||
dev_set_drvdata(dev, hdmi);
|
||||
|
||||
|
@ -882,7 +884,17 @@ static int inno_hdmi_bind(struct device *dev, struct device *master,
|
|||
ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq,
|
||||
inno_hdmi_irq, IRQF_SHARED,
|
||||
dev_name(dev), hdmi);
|
||||
if (ret < 0)
|
||||
goto err_cleanup_hdmi;
|
||||
|
||||
return 0;
|
||||
err_cleanup_hdmi:
|
||||
hdmi->connector.funcs->destroy(&hdmi->connector);
|
||||
hdmi->encoder.funcs->destroy(&hdmi->encoder);
|
||||
err_put_adapter:
|
||||
i2c_put_adapter(hdmi->ddc);
|
||||
err_disable_clk:
|
||||
clk_disable_unprepare(hdmi->pclk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -894,8 +906,8 @@ static void inno_hdmi_unbind(struct device *dev, struct device *master,
|
|||
hdmi->connector.funcs->destroy(&hdmi->connector);
|
||||
hdmi->encoder.funcs->destroy(&hdmi->encoder);
|
||||
|
||||
clk_disable_unprepare(hdmi->pclk);
|
||||
i2c_put_adapter(hdmi->ddc);
|
||||
clk_disable_unprepare(hdmi->pclk);
|
||||
}
|
||||
|
||||
static const struct component_ops inno_hdmi_ops = {
|
||||
|
|
|
@ -134,7 +134,7 @@ static int rockchip_drm_bind(struct device *dev)
|
|||
drm_dev->dev_private = private;
|
||||
|
||||
INIT_LIST_HEAD(&private->psr_list);
|
||||
spin_lock_init(&private->psr_list_lock);
|
||||
mutex_init(&private->psr_list_lock);
|
||||
|
||||
ret = rockchip_drm_init_iommu(drm_dev);
|
||||
if (ret)
|
||||
|
@ -314,6 +314,14 @@ static int compare_dev(struct device *dev, void *data)
|
|||
return dev == (struct device *)data;
|
||||
}
|
||||
|
||||
static void rockchip_drm_match_remove(struct device *dev)
|
||||
{
|
||||
struct device_link *link;
|
||||
|
||||
list_for_each_entry(link, &dev->links.consumers, s_node)
|
||||
device_link_del(link);
|
||||
}
|
||||
|
||||
static struct component_match *rockchip_drm_match_add(struct device *dev)
|
||||
{
|
||||
struct component_match *match = NULL;
|
||||
|
@ -331,10 +339,15 @@ static struct component_match *rockchip_drm_match_add(struct device *dev)
|
|||
|
||||
if (!d)
|
||||
break;
|
||||
|
||||
device_link_add(dev, d, DL_FLAG_STATELESS);
|
||||
component_match_add(dev, &match, compare_dev, d);
|
||||
} while (true);
|
||||
}
|
||||
|
||||
if (IS_ERR(match))
|
||||
rockchip_drm_match_remove(dev);
|
||||
|
||||
return match ?: ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
|
@ -411,13 +424,21 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(match))
|
||||
return PTR_ERR(match);
|
||||
|
||||
return component_master_add_with_match(dev, &rockchip_drm_ops, match);
|
||||
ret = component_master_add_with_match(dev, &rockchip_drm_ops, match);
|
||||
if (ret < 0) {
|
||||
rockchip_drm_match_remove(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_drm_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
component_master_del(&pdev->dev, &rockchip_drm_ops);
|
||||
|
||||
rockchip_drm_match_remove(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ struct rockchip_drm_private {
|
|||
struct mutex mm_lock;
|
||||
struct drm_mm mm;
|
||||
struct list_head psr_list;
|
||||
spinlock_t psr_list_lock;
|
||||
struct mutex psr_list_lock;
|
||||
};
|
||||
|
||||
int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "rockchip_drm_drv.h"
|
||||
#include "rockchip_drm_psr.h"
|
||||
|
||||
#define PSR_FLUSH_TIMEOUT msecs_to_jiffies(100)
|
||||
#define PSR_FLUSH_TIMEOUT_MS 100
|
||||
|
||||
enum psr_state {
|
||||
PSR_FLUSH,
|
||||
|
@ -30,11 +30,11 @@ struct psr_drv {
|
|||
struct list_head list;
|
||||
struct drm_encoder *encoder;
|
||||
|
||||
spinlock_t lock;
|
||||
struct mutex lock;
|
||||
bool active;
|
||||
enum psr_state state;
|
||||
|
||||
struct timer_list flush_timer;
|
||||
struct delayed_work flush_work;
|
||||
|
||||
void (*set)(struct drm_encoder *encoder, bool enable);
|
||||
};
|
||||
|
@ -43,9 +43,8 @@ static struct psr_drv *find_psr_by_crtc(struct drm_crtc *crtc)
|
|||
{
|
||||
struct rockchip_drm_private *drm_drv = crtc->dev->dev_private;
|
||||
struct psr_drv *psr;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
|
||||
mutex_lock(&drm_drv->psr_list_lock);
|
||||
list_for_each_entry(psr, &drm_drv->psr_list, list) {
|
||||
if (psr->encoder->crtc == crtc)
|
||||
goto out;
|
||||
|
@ -53,7 +52,24 @@ static struct psr_drv *find_psr_by_crtc(struct drm_crtc *crtc)
|
|||
psr = ERR_PTR(-ENODEV);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
|
||||
mutex_unlock(&drm_drv->psr_list_lock);
|
||||
return psr;
|
||||
}
|
||||
|
||||
static struct psr_drv *find_psr_by_encoder(struct drm_encoder *encoder)
|
||||
{
|
||||
struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
|
||||
struct psr_drv *psr;
|
||||
|
||||
mutex_lock(&drm_drv->psr_list_lock);
|
||||
list_for_each_entry(psr, &drm_drv->psr_list, list) {
|
||||
if (psr->encoder == encoder)
|
||||
goto out;
|
||||
}
|
||||
psr = ERR_PTR(-ENODEV);
|
||||
|
||||
out:
|
||||
mutex_unlock(&drm_drv->psr_list_lock);
|
||||
return psr;
|
||||
}
|
||||
|
||||
|
@ -94,43 +110,40 @@ static void psr_set_state_locked(struct psr_drv *psr, enum psr_state state)
|
|||
|
||||
static void psr_set_state(struct psr_drv *psr, enum psr_state state)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&psr->lock, flags);
|
||||
mutex_lock(&psr->lock);
|
||||
psr_set_state_locked(psr, state);
|
||||
spin_unlock_irqrestore(&psr->lock, flags);
|
||||
mutex_unlock(&psr->lock);
|
||||
}
|
||||
|
||||
static void psr_flush_handler(struct timer_list *t)
|
||||
static void psr_flush_handler(struct work_struct *work)
|
||||
{
|
||||
struct psr_drv *psr = from_timer(psr, t, flush_timer);
|
||||
unsigned long flags;
|
||||
struct psr_drv *psr = container_of(to_delayed_work(work),
|
||||
struct psr_drv, flush_work);
|
||||
|
||||
/* If the state has changed since we initiated the flush, do nothing */
|
||||
spin_lock_irqsave(&psr->lock, flags);
|
||||
mutex_lock(&psr->lock);
|
||||
if (psr->state == PSR_FLUSH)
|
||||
psr_set_state_locked(psr, PSR_ENABLE);
|
||||
spin_unlock_irqrestore(&psr->lock, flags);
|
||||
mutex_unlock(&psr->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* rockchip_drm_psr_activate - activate PSR on the given pipe
|
||||
* @crtc: CRTC to obtain the PSR encoder
|
||||
* @encoder: encoder to obtain the PSR encoder
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
int rockchip_drm_psr_activate(struct drm_crtc *crtc)
|
||||
int rockchip_drm_psr_activate(struct drm_encoder *encoder)
|
||||
{
|
||||
struct psr_drv *psr = find_psr_by_crtc(crtc);
|
||||
unsigned long flags;
|
||||
struct psr_drv *psr = find_psr_by_encoder(encoder);
|
||||
|
||||
if (IS_ERR(psr))
|
||||
return PTR_ERR(psr);
|
||||
|
||||
spin_lock_irqsave(&psr->lock, flags);
|
||||
mutex_lock(&psr->lock);
|
||||
psr->active = true;
|
||||
spin_unlock_irqrestore(&psr->lock, flags);
|
||||
mutex_unlock(&psr->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -138,23 +151,22 @@ EXPORT_SYMBOL(rockchip_drm_psr_activate);
|
|||
|
||||
/**
|
||||
* rockchip_drm_psr_deactivate - deactivate PSR on the given pipe
|
||||
* @crtc: CRTC to obtain the PSR encoder
|
||||
* @encoder: encoder to obtain the PSR encoder
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
int rockchip_drm_psr_deactivate(struct drm_crtc *crtc)
|
||||
int rockchip_drm_psr_deactivate(struct drm_encoder *encoder)
|
||||
{
|
||||
struct psr_drv *psr = find_psr_by_crtc(crtc);
|
||||
unsigned long flags;
|
||||
struct psr_drv *psr = find_psr_by_encoder(encoder);
|
||||
|
||||
if (IS_ERR(psr))
|
||||
return PTR_ERR(psr);
|
||||
|
||||
spin_lock_irqsave(&psr->lock, flags);
|
||||
mutex_lock(&psr->lock);
|
||||
psr->active = false;
|
||||
spin_unlock_irqrestore(&psr->lock, flags);
|
||||
del_timer_sync(&psr->flush_timer);
|
||||
mutex_unlock(&psr->lock);
|
||||
cancel_delayed_work_sync(&psr->flush_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -162,9 +174,8 @@ EXPORT_SYMBOL(rockchip_drm_psr_deactivate);
|
|||
|
||||
static void rockchip_drm_do_flush(struct psr_drv *psr)
|
||||
{
|
||||
mod_timer(&psr->flush_timer,
|
||||
round_jiffies_up(jiffies + PSR_FLUSH_TIMEOUT));
|
||||
psr_set_state(psr, PSR_FLUSH);
|
||||
mod_delayed_work(system_wq, &psr->flush_work, PSR_FLUSH_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -201,12 +212,11 @@ void rockchip_drm_psr_flush_all(struct drm_device *dev)
|
|||
{
|
||||
struct rockchip_drm_private *drm_drv = dev->dev_private;
|
||||
struct psr_drv *psr;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
|
||||
mutex_lock(&drm_drv->psr_list_lock);
|
||||
list_for_each_entry(psr, &drm_drv->psr_list, list)
|
||||
rockchip_drm_do_flush(psr);
|
||||
spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
|
||||
mutex_unlock(&drm_drv->psr_list_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(rockchip_drm_psr_flush_all);
|
||||
|
||||
|
@ -223,7 +233,6 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder,
|
|||
{
|
||||
struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
|
||||
struct psr_drv *psr;
|
||||
unsigned long flags;
|
||||
|
||||
if (!encoder || !psr_set)
|
||||
return -EINVAL;
|
||||
|
@ -232,17 +241,17 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder,
|
|||
if (!psr)
|
||||
return -ENOMEM;
|
||||
|
||||
timer_setup(&psr->flush_timer, psr_flush_handler, 0);
|
||||
spin_lock_init(&psr->lock);
|
||||
INIT_DELAYED_WORK(&psr->flush_work, psr_flush_handler);
|
||||
mutex_init(&psr->lock);
|
||||
|
||||
psr->active = true;
|
||||
psr->state = PSR_DISABLE;
|
||||
psr->encoder = encoder;
|
||||
psr->set = psr_set;
|
||||
|
||||
spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
|
||||
mutex_lock(&drm_drv->psr_list_lock);
|
||||
list_add_tail(&psr->list, &drm_drv->psr_list);
|
||||
spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
|
||||
mutex_unlock(&drm_drv->psr_list_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -260,16 +269,15 @@ void rockchip_drm_psr_unregister(struct drm_encoder *encoder)
|
|||
{
|
||||
struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
|
||||
struct psr_drv *psr, *n;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
|
||||
mutex_lock(&drm_drv->psr_list_lock);
|
||||
list_for_each_entry_safe(psr, n, &drm_drv->psr_list, list) {
|
||||
if (psr->encoder == encoder) {
|
||||
del_timer(&psr->flush_timer);
|
||||
cancel_delayed_work_sync(&psr->flush_work);
|
||||
list_del(&psr->list);
|
||||
kfree(psr);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
|
||||
mutex_unlock(&drm_drv->psr_list_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(rockchip_drm_psr_unregister);
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
void rockchip_drm_psr_flush_all(struct drm_device *dev);
|
||||
int rockchip_drm_psr_flush(struct drm_crtc *crtc);
|
||||
|
||||
int rockchip_drm_psr_activate(struct drm_crtc *crtc);
|
||||
int rockchip_drm_psr_deactivate(struct drm_crtc *crtc);
|
||||
int rockchip_drm_psr_activate(struct drm_encoder *encoder);
|
||||
int rockchip_drm_psr_deactivate(struct drm_encoder *encoder);
|
||||
|
||||
int rockchip_drm_psr_register(struct drm_encoder *encoder,
|
||||
void (*psr_set)(struct drm_encoder *, bool enable));
|
||||
|
|
|
@ -256,6 +256,9 @@ static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src,
|
|||
{
|
||||
uint16_t val = 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT;
|
||||
|
||||
if (vskiplines)
|
||||
*vskiplines = 0;
|
||||
|
||||
if (is_horizontal) {
|
||||
if (mode == SCALE_UP)
|
||||
val = GET_SCL_FT_BIC(src, dst);
|
||||
|
@ -296,7 +299,7 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,
|
|||
uint16_t vsu_mode;
|
||||
uint16_t lb_mode;
|
||||
uint32_t val;
|
||||
int vskiplines = 0;
|
||||
int vskiplines;
|
||||
|
||||
if (dst_w > 3840) {
|
||||
DRM_DEV_ERROR(vop->dev, "Maximum dst width (3840) exceeded\n");
|
||||
|
@ -566,8 +569,6 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc,
|
|||
|
||||
WARN_ON(vop->event);
|
||||
|
||||
rockchip_drm_psr_deactivate(&vop->crtc);
|
||||
|
||||
drm_crtc_vblank_off(crtc);
|
||||
|
||||
/*
|
||||
|
@ -627,7 +628,6 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
|
|||
struct vop_win *vop_win = to_vop_win(plane);
|
||||
const struct vop_win_data *win = vop_win->data;
|
||||
int ret;
|
||||
struct drm_rect clip = {};
|
||||
int min_scale = win->phy->scl ? FRAC_16_16(1, 8) :
|
||||
DRM_PLANE_HELPER_NO_SCALING;
|
||||
int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :
|
||||
|
@ -640,11 +640,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
|
|||
if (WARN_ON(!crtc_state))
|
||||
return -EINVAL;
|
||||
|
||||
if (crtc_state->enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
|
||||
ret = drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
min_scale, max_scale,
|
||||
true, true);
|
||||
if (ret)
|
||||
|
@ -939,8 +935,6 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc,
|
|||
clk_set_rate(vop->dclk, adjusted_mode->clock * 1000);
|
||||
|
||||
VOP_REG_SET(vop, common, standby, 0);
|
||||
|
||||
rockchip_drm_psr_activate(&vop->crtc);
|
||||
}
|
||||
|
||||
static bool vop_fs_irq_is_pending(struct vop *vop)
|
||||
|
|
|
@ -35,7 +35,6 @@ static int stm_gem_cma_dumb_create(struct drm_file *file,
|
|||
struct drm_device *dev,
|
||||
struct drm_mode_create_dumb *args)
|
||||
{
|
||||
#ifdef CONFIG_MMU
|
||||
unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
|
||||
|
||||
/*
|
||||
|
@ -44,7 +43,6 @@ static int stm_gem_cma_dumb_create(struct drm_file *file,
|
|||
*/
|
||||
args->pitch = roundup(min_pitch, 128);
|
||||
args->height = roundup(args->height, 4);
|
||||
#endif
|
||||
|
||||
return drm_gem_cma_dumb_create_internal(file, dev, args);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
config DRM_SUN4I
|
||||
tristate "DRM Support for Allwinner A10 Display Engine"
|
||||
depends on DRM && ARM && COMMON_CLK
|
||||
depends on DRM && (ARM || ARM64) && COMMON_CLK
|
||||
depends on ARCH_SUNXI || COMPILE_TEST
|
||||
select DRM_GEM_CMA_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
|
|
|
@ -12,6 +12,7 @@ sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o
|
|||
|
||||
sun8i-drm-hdmi-y += sun8i_dw_hdmi.o
|
||||
sun8i-drm-hdmi-y += sun8i_hdmi_phy.o
|
||||
sun8i-drm-hdmi-y += sun8i_hdmi_phy_clk.o
|
||||
|
||||
sun8i-mixer-y += sun8i_mixer.o sun8i_ui_layer.o \
|
||||
sun8i_vi_layer.o sun8i_ui_scaler.o \
|
||||
|
|
|
@ -92,13 +92,8 @@ void sun4i_backend_layer_enable(struct sun4i_backend *backend,
|
|||
SUN4I_BACKEND_MODCTL_LAY_EN(layer), val);
|
||||
}
|
||||
|
||||
static int sun4i_backend_drm_format_to_layer(struct drm_plane *plane,
|
||||
u32 format, u32 *mode)
|
||||
static int sun4i_backend_drm_format_to_layer(u32 format, u32 *mode)
|
||||
{
|
||||
if (plane && (plane->type == DRM_PLANE_TYPE_PRIMARY) &&
|
||||
(format == DRM_FORMAT_ARGB8888))
|
||||
format = DRM_FORMAT_XRGB8888;
|
||||
|
||||
switch (format) {
|
||||
case DRM_FORMAT_ARGB8888:
|
||||
*mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888;
|
||||
|
@ -191,8 +186,7 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend,
|
|||
DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n",
|
||||
interlaced ? "on" : "off");
|
||||
|
||||
ret = sun4i_backend_drm_format_to_layer(plane, fb->format->format,
|
||||
&val);
|
||||
ret = sun4i_backend_drm_format_to_layer(fb->format->format, &val);
|
||||
if (ret) {
|
||||
DRM_DEBUG_DRIVER("Invalid format\n");
|
||||
return ret;
|
||||
|
@ -211,7 +205,7 @@ int sun4i_backend_update_layer_frontend(struct sun4i_backend *backend,
|
|||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = sun4i_backend_drm_format_to_layer(NULL, fmt, &val);
|
||||
ret = sun4i_backend_drm_format_to_layer(fmt, &val);
|
||||
if (ret) {
|
||||
DRM_DEBUG_DRIVER("Invalid format\n");
|
||||
return ret;
|
||||
|
@ -275,12 +269,16 @@ int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend, int layer,
|
|||
struct drm_plane *plane)
|
||||
{
|
||||
struct drm_plane_state *state = plane->state;
|
||||
struct sun4i_layer_state *p_state = state_to_sun4i_layer_state(state);
|
||||
unsigned int priority = state->normalized_zpos;
|
||||
unsigned int pipe = p_state->pipe;
|
||||
|
||||
DRM_DEBUG_DRIVER("Setting layer %d's priority to %d\n", layer, priority);
|
||||
|
||||
DRM_DEBUG_DRIVER("Setting layer %d's priority to %d and pipe %d\n",
|
||||
layer, priority, pipe);
|
||||
regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_ATTCTL_REG0(layer),
|
||||
SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK |
|
||||
SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL_MASK,
|
||||
SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(p_state->pipe) |
|
||||
SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL(priority));
|
||||
|
||||
return 0;
|
||||
|
@ -325,12 +323,15 @@ static void sun4i_backend_atomic_begin(struct sunxi_engine *engine,
|
|||
static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
|
||||
struct drm_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_plane_state *plane_states[SUN4I_BACKEND_NUM_LAYERS] = { 0 };
|
||||
struct drm_atomic_state *state = crtc_state->state;
|
||||
struct drm_device *drm = state->dev;
|
||||
struct drm_plane *plane;
|
||||
unsigned int num_planes = 0;
|
||||
unsigned int num_alpha_planes = 0;
|
||||
unsigned int num_frontend_planes = 0;
|
||||
unsigned int current_pipe = 0;
|
||||
unsigned int i;
|
||||
|
||||
DRM_DEBUG_DRIVER("Starting checking our planes\n");
|
||||
|
||||
|
@ -361,9 +362,19 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
|
|||
if (fb->format->has_alpha)
|
||||
num_alpha_planes++;
|
||||
|
||||
DRM_DEBUG_DRIVER("Plane zpos is %d\n",
|
||||
plane_state->normalized_zpos);
|
||||
|
||||
/* Sort our planes by Zpos */
|
||||
plane_states[plane_state->normalized_zpos] = plane_state;
|
||||
|
||||
num_planes++;
|
||||
}
|
||||
|
||||
/* All our planes were disabled, bail out */
|
||||
if (!num_planes)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The hardware is a bit unusual here.
|
||||
*
|
||||
|
@ -400,6 +411,25 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* We can't have an alpha plane at the lowest position */
|
||||
if (plane_states[0]->fb->format->has_alpha)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 1; i < num_planes; i++) {
|
||||
struct drm_plane_state *p_state = plane_states[i];
|
||||
struct drm_framebuffer *fb = p_state->fb;
|
||||
struct sun4i_layer_state *s_state = state_to_sun4i_layer_state(p_state);
|
||||
|
||||
/*
|
||||
* The only alpha position is the lowest plane of the
|
||||
* second pipe.
|
||||
*/
|
||||
if (fb->format->has_alpha)
|
||||
current_pipe++;
|
||||
|
||||
s_state->pipe = current_pipe;
|
||||
}
|
||||
|
||||
if (num_frontend_planes > SUN4I_BACKEND_NUM_FRONTEND_LAYERS) {
|
||||
DRM_DEBUG_DRIVER("Too many planes going through the frontend, rejecting\n");
|
||||
return -EINVAL;
|
||||
|
|
|
@ -359,6 +359,7 @@ static const struct of_device_id sun4i_drv_of_table[] = {
|
|||
{ .compatible = "allwinner,sun7i-a20-display-engine" },
|
||||
{ .compatible = "allwinner,sun8i-a33-display-engine" },
|
||||
{ .compatible = "allwinner,sun8i-a83t-display-engine" },
|
||||
{ .compatible = "allwinner,sun8i-h3-display-engine" },
|
||||
{ .compatible = "allwinner,sun8i-v3s-display-engine" },
|
||||
{ }
|
||||
};
|
||||
|
|
|
@ -19,13 +19,6 @@
|
|||
#include "sun4i_layer.h"
|
||||
#include "sunxi_engine.h"
|
||||
|
||||
struct sun4i_plane_desc {
|
||||
enum drm_plane_type type;
|
||||
u8 pipe;
|
||||
const uint32_t *formats;
|
||||
uint32_t nformats;
|
||||
};
|
||||
|
||||
static void sun4i_backend_layer_reset(struct drm_plane *plane)
|
||||
{
|
||||
struct sun4i_layer *layer = plane_to_sun4i_layer(plane);
|
||||
|
@ -133,14 +126,7 @@ static const struct drm_plane_funcs sun4i_backend_layer_funcs = {
|
|||
.update_plane = drm_atomic_helper_update_plane,
|
||||
};
|
||||
|
||||
static const uint32_t sun4i_backend_layer_formats_primary[] = {
|
||||
DRM_FORMAT_ARGB8888,
|
||||
DRM_FORMAT_RGB888,
|
||||
DRM_FORMAT_RGB565,
|
||||
DRM_FORMAT_XRGB8888,
|
||||
};
|
||||
|
||||
static const uint32_t sun4i_backend_layer_formats_overlay[] = {
|
||||
static const uint32_t sun4i_backend_layer_formats[] = {
|
||||
DRM_FORMAT_ARGB8888,
|
||||
DRM_FORMAT_ARGB4444,
|
||||
DRM_FORMAT_ARGB1555,
|
||||
|
@ -151,24 +137,9 @@ static const uint32_t sun4i_backend_layer_formats_overlay[] = {
|
|||
DRM_FORMAT_XRGB8888,
|
||||
};
|
||||
|
||||
static const struct sun4i_plane_desc sun4i_backend_planes[] = {
|
||||
{
|
||||
.type = DRM_PLANE_TYPE_PRIMARY,
|
||||
.pipe = 0,
|
||||
.formats = sun4i_backend_layer_formats_primary,
|
||||
.nformats = ARRAY_SIZE(sun4i_backend_layer_formats_primary),
|
||||
},
|
||||
{
|
||||
.type = DRM_PLANE_TYPE_OVERLAY,
|
||||
.pipe = 1,
|
||||
.formats = sun4i_backend_layer_formats_overlay,
|
||||
.nformats = ARRAY_SIZE(sun4i_backend_layer_formats_overlay),
|
||||
},
|
||||
};
|
||||
|
||||
static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
|
||||
struct sun4i_backend *backend,
|
||||
const struct sun4i_plane_desc *plane)
|
||||
enum drm_plane_type type)
|
||||
{
|
||||
struct sun4i_layer *layer;
|
||||
int ret;
|
||||
|
@ -180,8 +151,9 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
|
|||
/* possible crtcs are set later */
|
||||
ret = drm_universal_plane_init(drm, &layer->plane, 0,
|
||||
&sun4i_backend_layer_funcs,
|
||||
plane->formats, plane->nformats,
|
||||
NULL, plane->type, NULL);
|
||||
sun4i_backend_layer_formats,
|
||||
ARRAY_SIZE(sun4i_backend_layer_formats),
|
||||
NULL, type, NULL);
|
||||
if (ret) {
|
||||
dev_err(drm->dev, "Couldn't initialize layer\n");
|
||||
return ERR_PTR(ret);
|
||||
|
@ -191,6 +163,9 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
|
|||
&sun4i_backend_layer_helper_funcs);
|
||||
layer->backend = backend;
|
||||
|
||||
drm_plane_create_zpos_property(&layer->plane, 0, 0,
|
||||
SUN4I_BACKEND_NUM_LAYERS - 1);
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
|
@ -207,25 +182,17 @@ struct drm_plane **sun4i_layers_init(struct drm_device *drm,
|
|||
if (!planes)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sun4i_backend_planes); i++) {
|
||||
const struct sun4i_plane_desc *plane = &sun4i_backend_planes[i];
|
||||
for (i = 0; i < SUN4I_BACKEND_NUM_LAYERS; i++) {
|
||||
enum drm_plane_type type = i ? DRM_PLANE_TYPE_OVERLAY : DRM_PLANE_TYPE_PRIMARY;
|
||||
struct sun4i_layer *layer;
|
||||
|
||||
layer = sun4i_layer_init_one(drm, backend, plane);
|
||||
layer = sun4i_layer_init_one(drm, backend, type);
|
||||
if (IS_ERR(layer)) {
|
||||
dev_err(drm->dev, "Couldn't initialize %s plane\n",
|
||||
i ? "overlay" : "primary");
|
||||
return ERR_CAST(layer);
|
||||
};
|
||||
|
||||
drm_plane_create_zpos_immutable_property(&layer->plane, i);
|
||||
|
||||
DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n",
|
||||
i ? "overlay" : "primary", plane->pipe);
|
||||
regmap_update_bits(engine->regs, SUN4I_BACKEND_ATTCTL_REG0(i),
|
||||
SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK,
|
||||
SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(plane->pipe));
|
||||
|
||||
layer->id = i;
|
||||
planes[i] = &layer->plane;
|
||||
};
|
||||
|
|
|
@ -24,6 +24,7 @@ struct sun4i_layer {
|
|||
|
||||
struct sun4i_layer_state {
|
||||
struct drm_plane_state state;
|
||||
unsigned int pipe;
|
||||
bool uses_frontend;
|
||||
};
|
||||
|
||||
|
|
|
@ -12,11 +12,158 @@
|
|||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#define SUN8I_HDMI_PHY_DBG_CTRL_REG 0x0000
|
||||
#define SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK BIT(0)
|
||||
#define SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK GENMASK(15, 8)
|
||||
#define SUN8I_HDMI_PHY_DBG_CTRL_POL_NHSYNC BIT(8)
|
||||
#define SUN8I_HDMI_PHY_DBG_CTRL_POL_NVSYNC BIT(9)
|
||||
#define SUN8I_HDMI_PHY_DBG_CTRL_ADDR_MASK GENMASK(23, 16)
|
||||
#define SUN8I_HDMI_PHY_DBG_CTRL_ADDR(addr) (addr << 16)
|
||||
|
||||
#define SUN8I_HDMI_PHY_REXT_CTRL_REG 0x0004
|
||||
#define SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN BIT(31)
|
||||
|
||||
#define SUN8I_HDMI_PHY_READ_EN_REG 0x0010
|
||||
#define SUN8I_HDMI_PHY_READ_EN_MAGIC 0x54524545
|
||||
|
||||
#define SUN8I_HDMI_PHY_UNSCRAMBLE_REG 0x0014
|
||||
#define SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC 0x42494E47
|
||||
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_REG 0x0020
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_REG_SWI BIT(31)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_REG_PWEND BIT(30)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_REG_PWENC BIT(29)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_REG_CALSW BIT(28)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_REG_SVRCAL(x) ((x) << 26)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_REG_SVBH(x) ((x) << 24)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_AMP_OPT BIT(23)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_EMP_OPT BIT(22)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_AMPCK_OPT BIT(21)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_EMPCK_OPT BIT(20)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_ENRCAL BIT(19)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_ENCALOG BIT(18)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_REG_SCKTMDS BIT(17)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_TMDSCLK_EN BIT(16)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK GENMASK(15, 12)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_TXEN_ALL (0xf << 12)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDSCLK BIT(11)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS2 BIT(10)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS1 BIT(9)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS0 BIT(8)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDSCLK BIT(7)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS2 BIT(6)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS1 BIT(5)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS0 BIT(4)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_CKEN BIT(3)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_LDOEN BIT(2)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_ENVBS BIT(1)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG1_ENBI BIT(0)
|
||||
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_REG 0x0024
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_M_EN BIT(31)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_PLLDBEN BIT(30)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_SEN BIT(29)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_REG_HPDPD BIT(28)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_REG_HPDEN BIT(27)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_REG_PLRCK BIT(26)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_REG_PLR(x) ((x) << 23)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_REG_DENCK BIT(22)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_REG_DEN BIT(21)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_REG_CD(x) ((x) << 19)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_REG_CKSS(x) ((x) << 17)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSWCK BIT(16)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSW BIT(15)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_REG_CSMPS(x) ((x) << 13)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(x) ((x) << 10)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_REG_BOOSTCK(x) ((x) << 8)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_REG_BOOST(x) ((x) << 6)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG2_REG_RESDI(x) ((x) << 0)
|
||||
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG3_REG 0x0028
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG3_REG_SLOWCK(x) ((x) << 30)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG3_REG_SLOW(x) ((x) << 28)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG3_REG_WIRE(x) ((x) << 18)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(x) ((x) << 14)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG3_REG_EMPCK(x) ((x) << 11)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(x) ((x) << 7)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG3_REG_EMP(x) ((x) << 4)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG3_SDAPD BIT(3)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG3_SDAEN BIT(2)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG3_SCLPD BIT(1)
|
||||
#define SUN8I_HDMI_PHY_ANA_CFG3_SCLEN BIT(0)
|
||||
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG1_REG 0x002c
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG1_REG_OD1 BIT(31)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG1_REG_OD BIT(30)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN BIT(29)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN BIT(28)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 BIT(27)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL BIT(26)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG1_PLLEN BIT(25)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(x) ((x) << 22)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(x) ((x) << 20)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG1_PLLDBEN BIT(19)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG1_CS BIT(18)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG1_CP_S(x) ((x) << 13)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(x) ((x) << 7)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG1_BWS BIT(6)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG1_B_IN_MSK GENMASK(5, 0)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG1_B_IN_SHIFT 0
|
||||
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_REG 0x0030
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_SV_H BIT(31)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_PDCLKSEL(x) ((x) << 29)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_CLKSTEP(x) ((x) << 27)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_PSET(x) ((x) << 24)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_PCLK_SEL BIT(23)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_AUTOSYNC_DIS BIT(22)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_VREG2_OUT_EN BIT(21)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_VREG1_OUT_EN BIT(20)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_VCOGAIN_EN BIT(19)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_VCOGAIN(x) ((x) << 16)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(x) ((x) << 12)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_VCO_RST_IN BIT(11)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_SINT_FRAC BIT(10)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_SDIV2 BIT(9)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_S(x) ((x) << 6)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_S6P25_7P5 BIT(5)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_S5_7 BIT(4)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK GENMASK(3, 0)
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_SHIFT 0
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG2_PREDIV(x) (((x) - 1) << 0)
|
||||
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG3_REG 0x0034
|
||||
#define SUN8I_HDMI_PHY_PLL_CFG3_SOUT_DIV2 BIT(0)
|
||||
|
||||
#define SUN8I_HDMI_PHY_ANA_STS_REG 0x0038
|
||||
#define SUN8I_HDMI_PHY_ANA_STS_B_OUT_SHIFT 11
|
||||
#define SUN8I_HDMI_PHY_ANA_STS_B_OUT_MSK GENMASK(16, 11)
|
||||
#define SUN8I_HDMI_PHY_ANA_STS_RCALEND2D BIT(7)
|
||||
#define SUN8I_HDMI_PHY_ANA_STS_RCAL_MASK GENMASK(5, 0)
|
||||
|
||||
#define SUN8I_HDMI_PHY_CEC_REG 0x003c
|
||||
|
||||
struct sun8i_hdmi_phy;
|
||||
|
||||
struct sun8i_hdmi_phy_variant {
|
||||
bool has_phy_clk;
|
||||
void (*phy_init)(struct sun8i_hdmi_phy *phy);
|
||||
void (*phy_disable)(struct dw_hdmi *hdmi,
|
||||
struct sun8i_hdmi_phy *phy);
|
||||
int (*phy_config)(struct dw_hdmi *hdmi,
|
||||
struct sun8i_hdmi_phy *phy,
|
||||
unsigned int clk_rate);
|
||||
};
|
||||
|
||||
struct sun8i_hdmi_phy {
|
||||
struct clk *clk_bus;
|
||||
struct clk *clk_mod;
|
||||
struct regmap *regs;
|
||||
struct reset_control *rst_phy;
|
||||
struct clk *clk_bus;
|
||||
struct clk *clk_mod;
|
||||
struct clk *clk_phy;
|
||||
struct clk *clk_pll0;
|
||||
unsigned int rcal;
|
||||
struct regmap *regs;
|
||||
struct reset_control *rst_phy;
|
||||
struct sun8i_hdmi_phy_variant *variant;
|
||||
};
|
||||
|
||||
struct sun8i_dw_hdmi {
|
||||
|
@ -41,4 +188,6 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi);
|
|||
void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
|
||||
const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void);
|
||||
|
||||
int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev);
|
||||
|
||||
#endif /* _SUN8I_DW_HDMI_H_ */
|
||||
|
|
|
@ -3,47 +3,21 @@
|
|||
* Copyright (c) 2018 Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include "sun8i_dw_hdmi.h"
|
||||
|
||||
#define SUN8I_HDMI_PHY_DBG_CTRL_REG 0x0000
|
||||
#define SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK BIT(0)
|
||||
#define SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK GENMASK(15, 8)
|
||||
#define SUN8I_HDMI_PHY_DBG_CTRL_POL(val) (val << 8)
|
||||
#define SUN8I_HDMI_PHY_DBG_CTRL_ADDR_MASK GENMASK(23, 16)
|
||||
#define SUN8I_HDMI_PHY_DBG_CTRL_ADDR(addr) (addr << 16)
|
||||
|
||||
#define SUN8I_HDMI_PHY_REXT_CTRL_REG 0x0004
|
||||
#define SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN BIT(31)
|
||||
|
||||
#define SUN8I_HDMI_PHY_READ_EN_REG 0x0010
|
||||
#define SUN8I_HDMI_PHY_READ_EN_MAGIC 0x54524545
|
||||
|
||||
#define SUN8I_HDMI_PHY_UNSCRAMBLE_REG 0x0014
|
||||
#define SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC 0x42494E47
|
||||
|
||||
/*
|
||||
* Address can be actually any value. Here is set to same value as
|
||||
* it is set in BSP driver.
|
||||
*/
|
||||
#define I2C_ADDR 0x69
|
||||
|
||||
static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data,
|
||||
struct drm_display_mode *mode)
|
||||
static int sun8i_hdmi_phy_config_a83t(struct dw_hdmi *hdmi,
|
||||
struct sun8i_hdmi_phy *phy,
|
||||
unsigned int clk_rate)
|
||||
{
|
||||
struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data;
|
||||
u32 val = 0;
|
||||
|
||||
if ((mode->flags & DRM_MODE_FLAG_NHSYNC) &&
|
||||
(mode->flags & DRM_MODE_FLAG_NHSYNC)) {
|
||||
val = 0x03;
|
||||
}
|
||||
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG,
|
||||
SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK,
|
||||
SUN8I_HDMI_PHY_DBG_CTRL_POL(val));
|
||||
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_REXT_CTRL_REG,
|
||||
SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN,
|
||||
SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN);
|
||||
|
@ -63,21 +37,21 @@ static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data,
|
|||
* release any documentation, explanation of this values can
|
||||
* be found in i.MX 6Dual/6Quad Reference Manual.
|
||||
*/
|
||||
if (mode->crtc_clock <= 27000) {
|
||||
if (clk_rate <= 27000000) {
|
||||
dw_hdmi_phy_i2c_write(hdmi, 0x01e0, 0x06);
|
||||
dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x15);
|
||||
dw_hdmi_phy_i2c_write(hdmi, 0x08da, 0x10);
|
||||
dw_hdmi_phy_i2c_write(hdmi, 0x0007, 0x19);
|
||||
dw_hdmi_phy_i2c_write(hdmi, 0x0318, 0x0e);
|
||||
dw_hdmi_phy_i2c_write(hdmi, 0x8009, 0x09);
|
||||
} else if (mode->crtc_clock <= 74250) {
|
||||
} else if (clk_rate <= 74250000) {
|
||||
dw_hdmi_phy_i2c_write(hdmi, 0x0540, 0x06);
|
||||
dw_hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
|
||||
dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10);
|
||||
dw_hdmi_phy_i2c_write(hdmi, 0x0007, 0x19);
|
||||
dw_hdmi_phy_i2c_write(hdmi, 0x02b5, 0x0e);
|
||||
dw_hdmi_phy_i2c_write(hdmi, 0x8009, 0x09);
|
||||
} else if (mode->crtc_clock <= 148500) {
|
||||
} else if (clk_rate <= 148500000) {
|
||||
dw_hdmi_phy_i2c_write(hdmi, 0x04a0, 0x06);
|
||||
dw_hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
|
||||
dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10);
|
||||
|
@ -100,12 +74,173 @@ static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data,
|
|||
dw_hdmi_phy_gen2_txpwron(hdmi, 1);
|
||||
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
static void sun8i_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data)
|
||||
static int sun8i_hdmi_phy_config_h3(struct dw_hdmi *hdmi,
|
||||
struct sun8i_hdmi_phy *phy,
|
||||
unsigned int clk_rate)
|
||||
{
|
||||
u32 pll_cfg1_init;
|
||||
u32 pll_cfg2_init;
|
||||
u32 ana_cfg1_end;
|
||||
u32 ana_cfg2_init;
|
||||
u32 ana_cfg3_init;
|
||||
u32 b_offset = 0;
|
||||
u32 val;
|
||||
|
||||
/* bandwidth / frequency independent settings */
|
||||
|
||||
pll_cfg1_init = SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN |
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN |
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(7) |
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(1) |
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_PLLDBEN |
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_CS |
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_CP_S(2) |
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(63) |
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_BWS;
|
||||
|
||||
pll_cfg2_init = SUN8I_HDMI_PHY_PLL_CFG2_SV_H |
|
||||
SUN8I_HDMI_PHY_PLL_CFG2_VCOGAIN_EN |
|
||||
SUN8I_HDMI_PHY_PLL_CFG2_SDIV2;
|
||||
|
||||
ana_cfg1_end = SUN8I_HDMI_PHY_ANA_CFG1_REG_SVBH(1) |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_AMP_OPT |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_EMP_OPT |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_AMPCK_OPT |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_EMPCK_OPT |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENRCAL |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENCALOG |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_REG_SCKTMDS |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_TMDSCLK_EN |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_TXEN_ALL |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDSCLK |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS2 |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS1 |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS0 |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS2 |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS1 |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS0 |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_CKEN |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_LDOEN |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENVBS |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENBI;
|
||||
|
||||
ana_cfg2_init = SUN8I_HDMI_PHY_ANA_CFG2_M_EN |
|
||||
SUN8I_HDMI_PHY_ANA_CFG2_REG_DENCK |
|
||||
SUN8I_HDMI_PHY_ANA_CFG2_REG_DEN |
|
||||
SUN8I_HDMI_PHY_ANA_CFG2_REG_CKSS(1) |
|
||||
SUN8I_HDMI_PHY_ANA_CFG2_REG_CSMPS(1);
|
||||
|
||||
ana_cfg3_init = SUN8I_HDMI_PHY_ANA_CFG3_REG_WIRE(0x3e0) |
|
||||
SUN8I_HDMI_PHY_ANA_CFG3_SDAEN |
|
||||
SUN8I_HDMI_PHY_ANA_CFG3_SCLEN;
|
||||
|
||||
/* bandwidth / frequency dependent settings */
|
||||
if (clk_rate <= 27000000) {
|
||||
pll_cfg1_init |= SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 |
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(32);
|
||||
pll_cfg2_init |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(4) |
|
||||
SUN8I_HDMI_PHY_PLL_CFG2_S(4);
|
||||
ana_cfg1_end |= SUN8I_HDMI_PHY_ANA_CFG1_REG_CALSW;
|
||||
ana_cfg2_init |= SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4) |
|
||||
SUN8I_HDMI_PHY_ANA_CFG2_REG_RESDI(phy->rcal);
|
||||
ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(3) |
|
||||
SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(5);
|
||||
} else if (clk_rate <= 74250000) {
|
||||
pll_cfg1_init |= SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 |
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(32);
|
||||
pll_cfg2_init |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(4) |
|
||||
SUN8I_HDMI_PHY_PLL_CFG2_S(5);
|
||||
ana_cfg1_end |= SUN8I_HDMI_PHY_ANA_CFG1_REG_CALSW;
|
||||
ana_cfg2_init |= SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4) |
|
||||
SUN8I_HDMI_PHY_ANA_CFG2_REG_RESDI(phy->rcal);
|
||||
ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(5) |
|
||||
SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(7);
|
||||
} else if (clk_rate <= 148500000) {
|
||||
pll_cfg1_init |= SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 |
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(32);
|
||||
pll_cfg2_init |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(4) |
|
||||
SUN8I_HDMI_PHY_PLL_CFG2_S(6);
|
||||
ana_cfg2_init |= SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSWCK |
|
||||
SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSW |
|
||||
SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(2);
|
||||
ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(7) |
|
||||
SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(9);
|
||||
} else {
|
||||
b_offset = 2;
|
||||
pll_cfg1_init |= SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(63);
|
||||
pll_cfg2_init |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(6) |
|
||||
SUN8I_HDMI_PHY_PLL_CFG2_S(7);
|
||||
ana_cfg2_init |= SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSWCK |
|
||||
SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSW |
|
||||
SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4);
|
||||
ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(9) |
|
||||
SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(13);
|
||||
}
|
||||
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK, 0);
|
||||
|
||||
regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, pll_cfg1_init);
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG,
|
||||
(u32)~SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK,
|
||||
pll_cfg2_init);
|
||||
usleep_range(10000, 15000);
|
||||
regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG3_REG,
|
||||
SUN8I_HDMI_PHY_PLL_CFG3_SOUT_DIV2);
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_PLLEN,
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_PLLEN);
|
||||
msleep(100);
|
||||
|
||||
/* get B value */
|
||||
regmap_read(phy->regs, SUN8I_HDMI_PHY_ANA_STS_REG, &val);
|
||||
val = (val & SUN8I_HDMI_PHY_ANA_STS_B_OUT_MSK) >>
|
||||
SUN8I_HDMI_PHY_ANA_STS_B_OUT_SHIFT;
|
||||
val = min(val + b_offset, (u32)0x3f);
|
||||
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_REG_OD1 |
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_REG_OD,
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_REG_OD1 |
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_REG_OD);
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
|
||||
SUN8I_HDMI_PHY_PLL_CFG1_B_IN_MSK,
|
||||
val << SUN8I_HDMI_PHY_PLL_CFG1_B_IN_SHIFT);
|
||||
msleep(100);
|
||||
regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, ana_cfg1_end);
|
||||
regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG2_REG, ana_cfg2_init);
|
||||
regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG3_REG, ana_cfg3_init);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data;
|
||||
u32 val = 0;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_NHSYNC)
|
||||
val |= SUN8I_HDMI_PHY_DBG_CTRL_POL_NHSYNC;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_NVSYNC)
|
||||
val |= SUN8I_HDMI_PHY_DBG_CTRL_POL_NVSYNC;
|
||||
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG,
|
||||
SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK, val);
|
||||
|
||||
if (phy->variant->has_phy_clk)
|
||||
clk_set_rate(phy->clk_phy, mode->crtc_clock * 1000);
|
||||
|
||||
return phy->variant->phy_config(hdmi, phy, mode->crtc_clock * 1000);
|
||||
};
|
||||
|
||||
static void sun8i_hdmi_phy_disable_a83t(struct dw_hdmi *hdmi,
|
||||
struct sun8i_hdmi_phy *phy)
|
||||
{
|
||||
dw_hdmi_phy_gen2_txpwron(hdmi, 0);
|
||||
dw_hdmi_phy_gen2_pddq(hdmi, 1);
|
||||
|
||||
|
@ -113,6 +248,23 @@ static void sun8i_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data)
|
|||
SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN, 0);
|
||||
}
|
||||
|
||||
static void sun8i_hdmi_phy_disable_h3(struct dw_hdmi *hdmi,
|
||||
struct sun8i_hdmi_phy *phy)
|
||||
{
|
||||
regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_LDOEN |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENVBS |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENBI);
|
||||
regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, 0);
|
||||
}
|
||||
|
||||
static void sun8i_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data)
|
||||
{
|
||||
struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data;
|
||||
|
||||
phy->variant->phy_disable(hdmi, phy);
|
||||
}
|
||||
|
||||
static const struct dw_hdmi_phy_ops sun8i_hdmi_phy_ops = {
|
||||
.init = &sun8i_hdmi_phy_config,
|
||||
.disable = &sun8i_hdmi_phy_disable,
|
||||
|
@ -121,16 +273,8 @@ static const struct dw_hdmi_phy_ops sun8i_hdmi_phy_ops = {
|
|||
.setup_hpd = &dw_hdmi_phy_setup_hpd,
|
||||
};
|
||||
|
||||
void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy)
|
||||
static void sun8i_hdmi_phy_init_a83t(struct sun8i_hdmi_phy *phy)
|
||||
{
|
||||
/* enable read access to HDMI controller */
|
||||
regmap_write(phy->regs, SUN8I_HDMI_PHY_READ_EN_REG,
|
||||
SUN8I_HDMI_PHY_READ_EN_MAGIC);
|
||||
|
||||
/* unscramble register offsets */
|
||||
regmap_write(phy->regs, SUN8I_HDMI_PHY_UNSCRAMBLE_REG,
|
||||
SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC);
|
||||
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG,
|
||||
SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK,
|
||||
SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK);
|
||||
|
@ -144,6 +288,91 @@ void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy)
|
|||
SUN8I_HDMI_PHY_DBG_CTRL_ADDR(I2C_ADDR));
|
||||
}
|
||||
|
||||
static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy *phy)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, 0);
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENBI,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENBI);
|
||||
udelay(5);
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_TMDSCLK_EN,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_TMDSCLK_EN);
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENVBS,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENVBS);
|
||||
usleep_range(10, 20);
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_LDOEN,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_LDOEN);
|
||||
udelay(5);
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_CKEN,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_CKEN);
|
||||
usleep_range(40, 100);
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENRCAL,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENRCAL);
|
||||
usleep_range(100, 200);
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENCALOG,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENCALOG);
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS0 |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS1 |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS2,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS0 |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS1 |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS2);
|
||||
|
||||
/* wait for calibration to finish */
|
||||
regmap_read_poll_timeout(phy->regs, SUN8I_HDMI_PHY_ANA_STS_REG, val,
|
||||
(val & SUN8I_HDMI_PHY_ANA_STS_RCALEND2D),
|
||||
100, 2000);
|
||||
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDSCLK,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDSCLK);
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS0 |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS1 |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS2 |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDSCLK,
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS0 |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS1 |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS2 |
|
||||
SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDSCLK);
|
||||
|
||||
/* enable DDC communication */
|
||||
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG3_REG,
|
||||
SUN8I_HDMI_PHY_ANA_CFG3_SCLEN |
|
||||
SUN8I_HDMI_PHY_ANA_CFG3_SDAEN,
|
||||
SUN8I_HDMI_PHY_ANA_CFG3_SCLEN |
|
||||
SUN8I_HDMI_PHY_ANA_CFG3_SDAEN);
|
||||
|
||||
/* set HW control of CEC pins */
|
||||
regmap_write(phy->regs, SUN8I_HDMI_PHY_CEC_REG, 0);
|
||||
|
||||
/* read calibration data */
|
||||
regmap_read(phy->regs, SUN8I_HDMI_PHY_ANA_STS_REG, &val);
|
||||
phy->rcal = (val & SUN8I_HDMI_PHY_ANA_STS_RCAL_MASK) >> 2;
|
||||
}
|
||||
|
||||
void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy)
|
||||
{
|
||||
/* enable read access to HDMI controller */
|
||||
regmap_write(phy->regs, SUN8I_HDMI_PHY_READ_EN_REG,
|
||||
SUN8I_HDMI_PHY_READ_EN_MAGIC);
|
||||
|
||||
/* unscramble register offsets */
|
||||
regmap_write(phy->regs, SUN8I_HDMI_PHY_UNSCRAMBLE_REG,
|
||||
SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC);
|
||||
|
||||
phy->variant->phy_init(phy);
|
||||
}
|
||||
|
||||
const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void)
|
||||
{
|
||||
return &sun8i_hdmi_phy_ops;
|
||||
|
@ -153,24 +382,46 @@ static struct regmap_config sun8i_hdmi_phy_regmap_config = {
|
|||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.max_register = SUN8I_HDMI_PHY_UNSCRAMBLE_REG,
|
||||
.max_register = SUN8I_HDMI_PHY_CEC_REG,
|
||||
.name = "phy"
|
||||
};
|
||||
|
||||
static const struct sun8i_hdmi_phy_variant sun8i_a83t_hdmi_phy = {
|
||||
.phy_init = &sun8i_hdmi_phy_init_a83t,
|
||||
.phy_disable = &sun8i_hdmi_phy_disable_a83t,
|
||||
.phy_config = &sun8i_hdmi_phy_config_a83t,
|
||||
};
|
||||
|
||||
static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = {
|
||||
.has_phy_clk = true,
|
||||
.phy_init = &sun8i_hdmi_phy_init_h3,
|
||||
.phy_disable = &sun8i_hdmi_phy_disable_h3,
|
||||
.phy_config = &sun8i_hdmi_phy_config_h3,
|
||||
};
|
||||
|
||||
static const struct of_device_id sun8i_hdmi_phy_of_table[] = {
|
||||
{ .compatible = "allwinner,sun8i-a83t-hdmi-phy" },
|
||||
{
|
||||
.compatible = "allwinner,sun8i-a83t-hdmi-phy",
|
||||
.data = &sun8i_a83t_hdmi_phy,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun8i-h3-hdmi-phy",
|
||||
.data = &sun8i_h3_hdmi_phy,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
|
||||
{
|
||||
const struct of_device_id *match;
|
||||
struct device *dev = hdmi->dev;
|
||||
struct sun8i_hdmi_phy *phy;
|
||||
struct resource res;
|
||||
void __iomem *regs;
|
||||
int ret;
|
||||
|
||||
if (!of_match_node(sun8i_hdmi_phy_of_table, node)) {
|
||||
match = of_match_node(sun8i_hdmi_phy_of_table, node);
|
||||
if (!match) {
|
||||
dev_err(dev, "Incompatible HDMI PHY\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -179,6 +430,8 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
|
|||
if (!phy)
|
||||
return -ENOMEM;
|
||||
|
||||
phy->variant = (struct sun8i_hdmi_phy_variant *)match->data;
|
||||
|
||||
ret = of_address_to_resource(node, 0, &res);
|
||||
if (ret) {
|
||||
dev_err(dev, "phy: Couldn't get our resources\n");
|
||||
|
@ -211,11 +464,26 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
|
|||
goto err_put_clk_bus;
|
||||
}
|
||||
|
||||
if (phy->variant->has_phy_clk) {
|
||||
phy->clk_pll0 = of_clk_get_by_name(node, "pll-0");
|
||||
if (IS_ERR(phy->clk_pll0)) {
|
||||
dev_err(dev, "Could not get pll-0 clock\n");
|
||||
ret = PTR_ERR(phy->clk_pll0);
|
||||
goto err_put_clk_mod;
|
||||
}
|
||||
|
||||
ret = sun8i_phy_clk_create(phy, dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Couldn't create the PHY clock\n");
|
||||
goto err_put_clk_pll0;
|
||||
}
|
||||
}
|
||||
|
||||
phy->rst_phy = of_reset_control_get_shared(node, "phy");
|
||||
if (IS_ERR(phy->rst_phy)) {
|
||||
dev_err(dev, "Could not get phy reset control\n");
|
||||
ret = PTR_ERR(phy->rst_phy);
|
||||
goto err_put_clk_mod;
|
||||
goto err_put_clk_pll0;
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(phy->rst_phy);
|
||||
|
@ -246,6 +514,9 @@ err_deassert_rst_phy:
|
|||
reset_control_assert(phy->rst_phy);
|
||||
err_put_rst_phy:
|
||||
reset_control_put(phy->rst_phy);
|
||||
err_put_clk_pll0:
|
||||
if (phy->variant->has_phy_clk)
|
||||
clk_put(phy->clk_pll0);
|
||||
err_put_clk_mod:
|
||||
clk_put(phy->clk_mod);
|
||||
err_put_clk_bus:
|
||||
|
@ -265,6 +536,8 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi)
|
|||
|
||||
reset_control_put(phy->rst_phy);
|
||||
|
||||
if (phy->variant->has_phy_clk)
|
||||
clk_put(phy->clk_pll0);
|
||||
clk_put(phy->clk_mod);
|
||||
clk_put(phy->clk_bus);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2018 Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#include "sun8i_dw_hdmi.h"
|
||||
|
||||
struct sun8i_phy_clk {
|
||||
struct clk_hw hw;
|
||||
struct sun8i_hdmi_phy *phy;
|
||||
};
|
||||
|
||||
static inline struct sun8i_phy_clk *hw_to_phy_clk(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw, struct sun8i_phy_clk, hw);
|
||||
}
|
||||
|
||||
static int sun8i_phy_clk_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
unsigned long rate = req->rate;
|
||||
unsigned long best_rate = 0;
|
||||
struct clk_hw *parent;
|
||||
int best_div = 1;
|
||||
int i;
|
||||
|
||||
parent = clk_hw_get_parent(hw);
|
||||
|
||||
for (i = 1; i <= 16; i++) {
|
||||
unsigned long ideal = rate * i;
|
||||
unsigned long rounded;
|
||||
|
||||
rounded = clk_hw_round_rate(parent, ideal);
|
||||
|
||||
if (rounded == ideal) {
|
||||
best_rate = rounded;
|
||||
best_div = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!best_rate ||
|
||||
abs(rate - rounded / i) <
|
||||
abs(rate - best_rate / best_div)) {
|
||||
best_rate = rounded;
|
||||
best_div = i;
|
||||
}
|
||||
}
|
||||
|
||||
req->rate = best_rate / best_div;
|
||||
req->best_parent_rate = best_rate;
|
||||
req->best_parent_hw = parent;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long sun8i_phy_clk_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct sun8i_phy_clk *priv = hw_to_phy_clk(hw);
|
||||
u32 reg;
|
||||
|
||||
regmap_read(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG, ®);
|
||||
reg = ((reg >> SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_SHIFT) &
|
||||
SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK) + 1;
|
||||
|
||||
return parent_rate / reg;
|
||||
}
|
||||
|
||||
static int sun8i_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct sun8i_phy_clk *priv = hw_to_phy_clk(hw);
|
||||
unsigned long best_rate = 0;
|
||||
u8 best_m = 0, m;
|
||||
|
||||
for (m = 1; m <= 16; m++) {
|
||||
unsigned long tmp_rate = parent_rate / m;
|
||||
|
||||
if (tmp_rate > rate)
|
||||
continue;
|
||||
|
||||
if (!best_rate ||
|
||||
(rate - tmp_rate) < (rate - best_rate)) {
|
||||
best_rate = tmp_rate;
|
||||
best_m = m;
|
||||
}
|
||||
}
|
||||
|
||||
regmap_update_bits(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG,
|
||||
SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK,
|
||||
SUN8I_HDMI_PHY_PLL_CFG2_PREDIV(best_m));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops sun8i_phy_clk_ops = {
|
||||
.determine_rate = sun8i_phy_clk_determine_rate,
|
||||
.recalc_rate = sun8i_phy_clk_recalc_rate,
|
||||
.set_rate = sun8i_phy_clk_set_rate,
|
||||
};
|
||||
|
||||
int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev)
|
||||
{
|
||||
struct clk_init_data init;
|
||||
struct sun8i_phy_clk *priv;
|
||||
const char *parents[1];
|
||||
|
||||
parents[0] = __clk_get_name(phy->clk_pll0);
|
||||
if (!parents[0])
|
||||
return -ENODEV;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
init.name = "hdmi-phy-clk";
|
||||
init.ops = &sun8i_phy_clk_ops;
|
||||
init.parent_names = parents;
|
||||
init.num_parents = 1;
|
||||
init.flags = CLK_SET_RATE_PARENT;
|
||||
|
||||
priv->phy = phy;
|
||||
priv->hw.init = &init;
|
||||
|
||||
phy->clk_phy = devm_clk_register(dev, &priv->hw);
|
||||
if (IS_ERR(phy->clk_phy))
|
||||
return PTR_ERR(phy->clk_phy);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -492,6 +492,14 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = {
|
|||
.vi_num = 1,
|
||||
};
|
||||
|
||||
static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = {
|
||||
.ccsc = 0,
|
||||
.mod_rate = 432000000,
|
||||
.scaler_mask = 0xf,
|
||||
.ui_num = 3,
|
||||
.vi_num = 1,
|
||||
};
|
||||
|
||||
static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
|
||||
.vi_num = 2,
|
||||
.ui_num = 1,
|
||||
|
@ -509,6 +517,10 @@ static const struct of_device_id sun8i_mixer_of_table[] = {
|
|||
.compatible = "allwinner,sun8i-a83t-de2-mixer-1",
|
||||
.data = &sun8i_a83t_mixer1_cfg,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun8i-h3-de2-mixer-0",
|
||||
.data = &sun8i_h3_mixer0_cfg,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun8i-v3s-de2-mixer",
|
||||
.data = &sun8i_v3s_mixer_cfg,
|
||||
|
|
|
@ -211,7 +211,6 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane,
|
|||
struct drm_crtc *crtc = state->crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
int min_scale, max_scale;
|
||||
struct drm_rect clip = {};
|
||||
|
||||
if (!crtc)
|
||||
return 0;
|
||||
|
@ -220,10 +219,6 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane,
|
|||
if (WARN_ON(!crtc_state))
|
||||
return -EINVAL;
|
||||
|
||||
if (crtc_state->enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
min_scale = DRM_PLANE_HELPER_NO_SCALING;
|
||||
max_scale = DRM_PLANE_HELPER_NO_SCALING;
|
||||
|
||||
|
@ -232,7 +227,7 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane,
|
|||
max_scale = SUN8I_UI_SCALER_SCALE_MAX;
|
||||
}
|
||||
|
||||
return drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
|
||||
return drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
min_scale, max_scale,
|
||||
true, true);
|
||||
}
|
||||
|
|
|
@ -239,7 +239,6 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
|
|||
struct drm_crtc *crtc = state->crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
int min_scale, max_scale;
|
||||
struct drm_rect clip = {};
|
||||
|
||||
if (!crtc)
|
||||
return 0;
|
||||
|
@ -248,10 +247,6 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
|
|||
if (WARN_ON(!crtc_state))
|
||||
return -EINVAL;
|
||||
|
||||
if (crtc_state->enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
min_scale = DRM_PLANE_HELPER_NO_SCALING;
|
||||
max_scale = DRM_PLANE_HELPER_NO_SCALING;
|
||||
|
||||
|
@ -260,7 +255,7 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
|
|||
max_scale = SUN8I_VI_SCALER_SCALE_MAX;
|
||||
}
|
||||
|
||||
return drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
|
||||
return drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
min_scale, max_scale,
|
||||
true, true);
|
||||
}
|
||||
|
|
|
@ -82,7 +82,6 @@ int tegra_plane_state_add(struct tegra_plane *plane,
|
|||
{
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct tegra_dc_state *tegra;
|
||||
struct drm_rect clip = {};
|
||||
int err;
|
||||
|
||||
/* Propagate errors from allocation or locking failures. */
|
||||
|
@ -90,12 +89,8 @@ int tegra_plane_state_add(struct tegra_plane *plane,
|
|||
if (IS_ERR(crtc_state))
|
||||
return PTR_ERR(crtc_state);
|
||||
|
||||
if (crtc_state->enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
/* Check plane state for visibility and calculate clipping bounds */
|
||||
err = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
|
||||
err = drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
0, INT_MAX, true, true);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
|
|
@ -23,6 +23,7 @@ config TINYDRM_ILI9225
|
|||
config TINYDRM_MI0283QT
|
||||
tristate "DRM support for MI0283QT"
|
||||
depends on DRM_TINYDRM && SPI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select TINYDRM_MIPI_DBI
|
||||
help
|
||||
DRM driver for the Multi-Inno MI0283QT display panel
|
||||
|
@ -54,6 +55,7 @@ config TINYDRM_ST7586
|
|||
config TINYDRM_ST7735R
|
||||
tristate "DRM support for Sitronix ST7735R display panels"
|
||||
depends on DRM_TINYDRM && SPI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
select TINYDRM_MIPI_DBI
|
||||
help
|
||||
DRM driver Sitronix ST7735R with one of the following LCDs:
|
||||
|
|
|
@ -273,16 +273,20 @@ static void tve200_display_update(struct drm_simple_display_pipe *pipe,
|
|||
}
|
||||
}
|
||||
|
||||
int tve200_enable_vblank(struct drm_device *drm, unsigned int crtc)
|
||||
static int tve200_display_enable_vblank(struct drm_simple_display_pipe *pipe)
|
||||
{
|
||||
struct drm_crtc *crtc = &pipe->crtc;
|
||||
struct drm_device *drm = crtc->dev;
|
||||
struct tve200_drm_dev_private *priv = drm->dev_private;
|
||||
|
||||
writel(TVE200_INT_V_STATUS, priv->regs + TVE200_INT_EN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tve200_disable_vblank(struct drm_device *drm, unsigned int crtc)
|
||||
static void tve200_display_disable_vblank(struct drm_simple_display_pipe *pipe)
|
||||
{
|
||||
struct drm_crtc *crtc = &pipe->crtc;
|
||||
struct drm_device *drm = crtc->dev;
|
||||
struct tve200_drm_dev_private *priv = drm->dev_private;
|
||||
|
||||
writel(0, priv->regs + TVE200_INT_EN);
|
||||
|
@ -300,6 +304,8 @@ static const struct drm_simple_display_pipe_funcs tve200_display_funcs = {
|
|||
.disable = tve200_display_disable,
|
||||
.update = tve200_display_update,
|
||||
.prepare_fb = tve200_display_prepare_fb,
|
||||
.enable_vblank = tve200_display_enable_vblank,
|
||||
.disable_vblank = tve200_display_disable_vblank,
|
||||
};
|
||||
|
||||
int tve200_display_init(struct drm_device *drm)
|
||||
|
|
|
@ -113,8 +113,6 @@ struct tve200_drm_dev_private {
|
|||
container_of(x, struct tve200_drm_connector, connector)
|
||||
|
||||
int tve200_display_init(struct drm_device *dev);
|
||||
int tve200_enable_vblank(struct drm_device *drm, unsigned int crtc);
|
||||
void tve200_disable_vblank(struct drm_device *drm, unsigned int crtc);
|
||||
irqreturn_t tve200_irq(int irq, void *data);
|
||||
int tve200_connector_init(struct drm_device *dev);
|
||||
int tve200_encoder_init(struct drm_device *dev);
|
||||
|
|
|
@ -162,9 +162,6 @@ static struct drm_driver tve200_drm_driver = {
|
|||
.gem_free_object_unlocked = drm_gem_cma_free_object,
|
||||
.gem_vm_ops = &drm_gem_cma_vm_ops,
|
||||
|
||||
.enable_vblank = tve200_enable_vblank,
|
||||
.disable_vblank = tve200_disable_vblank,
|
||||
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
.gem_prime_import = drm_gem_prime_import,
|
||||
|
|
|
@ -681,7 +681,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
|
|||
drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
|
||||
HDMI_WRITE(VC4_HDMI_FIFO_CTL,
|
||||
drift | VC4_HDMI_FIFO_CTL_RECENTER);
|
||||
udelay(1000);
|
||||
usleep_range(1000, 1100);
|
||||
HDMI_WRITE(VC4_HDMI_FIFO_CTL,
|
||||
drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
|
||||
HDMI_WRITE(VC4_HDMI_FIFO_CTL,
|
||||
|
|
|
@ -215,6 +215,7 @@ int vc4_kms_load(struct drm_device *dev)
|
|||
dev->mode_config.funcs = &vc4_mode_funcs;
|
||||
dev->mode_config.preferred_depth = 24;
|
||||
dev->mode_config.async_page_flip = true;
|
||||
dev->mode_config.allow_fb_modifiers = true;
|
||||
|
||||
drm_mode_config_reset(dev);
|
||||
|
||||
|
|
|
@ -906,6 +906,32 @@ out:
|
|||
ctx);
|
||||
}
|
||||
|
||||
static bool vc4_format_mod_supported(struct drm_plane *plane,
|
||||
uint32_t format,
|
||||
uint64_t modifier)
|
||||
{
|
||||
/* Support T_TILING for RGB formats only. */
|
||||
switch (format) {
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
case DRM_FORMAT_ARGB8888:
|
||||
case DRM_FORMAT_ABGR8888:
|
||||
case DRM_FORMAT_XBGR8888:
|
||||
case DRM_FORMAT_RGB565:
|
||||
case DRM_FORMAT_BGR565:
|
||||
case DRM_FORMAT_ARGB1555:
|
||||
case DRM_FORMAT_XRGB1555:
|
||||
return true;
|
||||
case DRM_FORMAT_YUV422:
|
||||
case DRM_FORMAT_YVU422:
|
||||
case DRM_FORMAT_YUV420:
|
||||
case DRM_FORMAT_YVU420:
|
||||
case DRM_FORMAT_NV12:
|
||||
case DRM_FORMAT_NV16:
|
||||
default:
|
||||
return (modifier == DRM_FORMAT_MOD_LINEAR);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct drm_plane_funcs vc4_plane_funcs = {
|
||||
.update_plane = vc4_update_plane,
|
||||
.disable_plane = drm_atomic_helper_disable_plane,
|
||||
|
@ -914,6 +940,7 @@ static const struct drm_plane_funcs vc4_plane_funcs = {
|
|||
.reset = vc4_plane_reset,
|
||||
.atomic_duplicate_state = vc4_plane_duplicate_state,
|
||||
.atomic_destroy_state = vc4_plane_destroy_state,
|
||||
.format_mod_supported = vc4_format_mod_supported,
|
||||
};
|
||||
|
||||
struct drm_plane *vc4_plane_init(struct drm_device *dev,
|
||||
|
@ -925,6 +952,11 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
|
|||
u32 num_formats = 0;
|
||||
int ret = 0;
|
||||
unsigned i;
|
||||
static const uint64_t modifiers[] = {
|
||||
DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
|
||||
DRM_FORMAT_MOD_LINEAR,
|
||||
DRM_FORMAT_MOD_INVALID
|
||||
};
|
||||
|
||||
vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane),
|
||||
GFP_KERNEL);
|
||||
|
@ -945,7 +977,7 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
|
|||
ret = drm_universal_plane_init(dev, plane, 0,
|
||||
&vc4_plane_funcs,
|
||||
formats, num_formats,
|
||||
NULL, type, NULL);
|
||||
modifiers, type, NULL);
|
||||
|
||||
drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
|
||||
|
||||
|
|
|
@ -61,9 +61,9 @@ static void virtio_gpu_user_framebuffer_destroy(struct drm_framebuffer *fb)
|
|||
static int
|
||||
virtio_gpu_framebuffer_surface_dirty(struct drm_framebuffer *fb,
|
||||
struct drm_file *file_priv,
|
||||
unsigned flags, unsigned color,
|
||||
unsigned int flags, unsigned int color,
|
||||
struct drm_clip_rect *clips,
|
||||
unsigned num_clips)
|
||||
unsigned int num_clips)
|
||||
{
|
||||
struct virtio_gpu_framebuffer *virtio_gpu_fb
|
||||
= to_virtio_gpu_framebuffer(fb);
|
||||
|
@ -96,6 +96,7 @@ virtio_gpu_framebuffer_init(struct drm_device *dev,
|
|||
{
|
||||
int ret;
|
||||
struct virtio_gpu_object *bo;
|
||||
|
||||
vgfb->obj = obj;
|
||||
|
||||
bo = gem_to_virtio_gpu_obj(obj);
|
||||
|
@ -387,7 +388,7 @@ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev)
|
|||
for (i = 0 ; i < vgdev->num_scanouts; ++i)
|
||||
vgdev_output_init(vgdev, i);
|
||||
|
||||
drm_mode_config_reset(vgdev->ddev);
|
||||
drm_mode_config_reset(vgdev->ddev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ static int virtio_gpu_probe(struct virtio_device *vdev)
|
|||
static void virtio_gpu_remove(struct virtio_device *vdev)
|
||||
{
|
||||
struct drm_device *dev = vdev->priv;
|
||||
|
||||
drm_put_dev(dev);
|
||||
}
|
||||
|
||||
|
@ -112,7 +113,6 @@ static const struct file_operations virtio_gpu_driver_fops = {
|
|||
.llseek = noop_llseek,
|
||||
};
|
||||
|
||||
|
||||
static struct drm_driver driver = {
|
||||
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER | DRIVER_ATOMIC,
|
||||
.load = virtio_gpu_driver_load,
|
||||
|
|
|
@ -246,7 +246,7 @@ int virtio_gpu_fbdev_init(struct virtio_gpu_device *vgdev);
|
|||
void virtio_gpu_fbdev_fini(struct virtio_gpu_device *vgdev);
|
||||
int virtio_gpu_surface_dirty(struct virtio_gpu_framebuffer *qfb,
|
||||
struct drm_clip_rect *clips,
|
||||
unsigned num_clips);
|
||||
unsigned int num_clips);
|
||||
/* virtio vg */
|
||||
int virtio_gpu_alloc_vbufs(struct virtio_gpu_device *vgdev);
|
||||
void virtio_gpu_free_vbufs(struct virtio_gpu_device *vgdev);
|
||||
|
@ -363,12 +363,12 @@ int virtgpu_gem_prime_pin(struct drm_gem_object *obj);
|
|||
void virtgpu_gem_prime_unpin(struct drm_gem_object *obj);
|
||||
struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj);
|
||||
struct drm_gem_object *virtgpu_gem_prime_import_sg_table(
|
||||
struct drm_device *dev, struct dma_buf_attachment *attach,
|
||||
struct sg_table *sgt);
|
||||
struct drm_device *dev, struct dma_buf_attachment *attach,
|
||||
struct sg_table *sgt);
|
||||
void *virtgpu_gem_prime_vmap(struct drm_gem_object *obj);
|
||||
void virtgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
|
||||
int virtgpu_gem_prime_mmap(struct drm_gem_object *obj,
|
||||
struct vm_area_struct *vma);
|
||||
struct vm_area_struct *vma);
|
||||
|
||||
static inline struct virtio_gpu_object*
|
||||
virtio_gpu_object_ref(struct virtio_gpu_object *bo)
|
||||
|
|
|
@ -118,7 +118,7 @@ static int virtio_gpu_dirty_update(struct virtio_gpu_framebuffer *fb,
|
|||
|
||||
int virtio_gpu_surface_dirty(struct virtio_gpu_framebuffer *vgfb,
|
||||
struct drm_clip_rect *clips,
|
||||
unsigned num_clips)
|
||||
unsigned int num_clips)
|
||||
{
|
||||
struct virtio_gpu_device *vgdev = vgfb->base.dev->dev_private;
|
||||
struct virtio_gpu_object *obj = gem_to_virtio_gpu_obj(vgfb->obj);
|
||||
|
@ -127,6 +127,7 @@ int virtio_gpu_surface_dirty(struct virtio_gpu_framebuffer *vgfb,
|
|||
int left, right, top, bottom;
|
||||
int i;
|
||||
int inc = 1;
|
||||
|
||||
if (!num_clips) {
|
||||
num_clips = 1;
|
||||
clips = &norect;
|
||||
|
@ -172,6 +173,7 @@ static void virtio_gpu_3d_fillrect(struct fb_info *info,
|
|||
const struct fb_fillrect *rect)
|
||||
{
|
||||
struct virtio_gpu_fbdev *vfbdev = info->par;
|
||||
|
||||
drm_fb_helper_sys_fillrect(info, rect);
|
||||
virtio_gpu_dirty_update(&vfbdev->vgfb, true, rect->dx, rect->dy,
|
||||
rect->width, rect->height);
|
||||
|
@ -182,6 +184,7 @@ static void virtio_gpu_3d_copyarea(struct fb_info *info,
|
|||
const struct fb_copyarea *area)
|
||||
{
|
||||
struct virtio_gpu_fbdev *vfbdev = info->par;
|
||||
|
||||
drm_fb_helper_sys_copyarea(info, area);
|
||||
virtio_gpu_dirty_update(&vfbdev->vgfb, true, area->dx, area->dy,
|
||||
area->width, area->height);
|
||||
|
@ -192,6 +195,7 @@ static void virtio_gpu_3d_imageblit(struct fb_info *info,
|
|||
const struct fb_image *image)
|
||||
{
|
||||
struct virtio_gpu_fbdev *vfbdev = info->par;
|
||||
|
||||
drm_fb_helper_sys_imageblit(info, image);
|
||||
virtio_gpu_dirty_update(&vfbdev->vgfb, true, image->dx, image->dy,
|
||||
image->width, image->height);
|
||||
|
|
|
@ -124,6 +124,7 @@ int virtio_gpu_mode_dumb_mmap(struct drm_file *file_priv,
|
|||
{
|
||||
struct drm_gem_object *gobj;
|
||||
struct virtio_gpu_object *obj;
|
||||
|
||||
BUG_ON(!offset_p);
|
||||
gobj = drm_gem_object_lookup(file_priv, handle);
|
||||
if (gobj == NULL)
|
||||
|
|
|
@ -83,6 +83,7 @@ static void virtio_gpu_unref_list(struct list_head *head)
|
|||
struct ttm_validate_buffer *buf;
|
||||
struct ttm_buffer_object *bo;
|
||||
struct virtio_gpu_object *qobj;
|
||||
|
||||
list_for_each_entry(buf, head, head) {
|
||||
bo = buf->bo;
|
||||
qobj = container_of(bo, struct virtio_gpu_object, tbo);
|
||||
|
@ -478,6 +479,7 @@ static int virtio_gpu_get_caps_ioctl(struct drm_device *dev,
|
|||
int ret;
|
||||
struct virtio_gpu_drv_cap_cache *cache_ent;
|
||||
void *ptr;
|
||||
|
||||
if (vgdev->num_capsets == 0)
|
||||
return -ENOSYS;
|
||||
|
||||
|
@ -532,33 +534,34 @@ copy_exit:
|
|||
|
||||
struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = {
|
||||
DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl,
|
||||
DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
|
||||
|
||||
DRM_IOCTL_DEF_DRV(VIRTGPU_EXECBUFFER, virtio_gpu_execbuffer_ioctl,
|
||||
DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
|
||||
|
||||
DRM_IOCTL_DEF_DRV(VIRTGPU_GETPARAM, virtio_gpu_getparam_ioctl,
|
||||
DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
|
||||
|
||||
DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE,
|
||||
virtio_gpu_resource_create_ioctl,
|
||||
DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
|
||||
|
||||
DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_INFO, virtio_gpu_resource_info_ioctl,
|
||||
DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
|
||||
|
||||
/* make transfer async to the main ring? - no sure, can we
|
||||
thread these in the underlying GL */
|
||||
* thread these in the underlying GL
|
||||
*/
|
||||
DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_FROM_HOST,
|
||||
virtio_gpu_transfer_from_host_ioctl,
|
||||
DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_TO_HOST,
|
||||
virtio_gpu_transfer_to_host_ioctl,
|
||||
DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
|
||||
|
||||
DRM_IOCTL_DEF_DRV(VIRTGPU_WAIT, virtio_gpu_wait_ioctl,
|
||||
DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
|
||||
|
||||
DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl,
|
||||
DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
|
||||
DRM_AUTH | DRM_UNLOCKED | DRM_RENDER_ALLOW),
|
||||
};
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
#include "virtgpu_drv.h"
|
||||
|
||||
/* Empty Implementations as there should not be any other driver for a virtual
|
||||
* device that might share buffers with virtgpu */
|
||||
* device that might share buffers with virtgpu
|
||||
*/
|
||||
|
||||
int virtgpu_gem_prime_pin(struct drm_gem_object *obj)
|
||||
{
|
||||
|
@ -38,7 +39,6 @@ void virtgpu_gem_prime_unpin(struct drm_gem_object *obj)
|
|||
WARN_ONCE(1, "not implemented");
|
||||
}
|
||||
|
||||
|
||||
struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj)
|
||||
{
|
||||
WARN_ONCE(1, "not implemented");
|
||||
|
|
|
@ -177,7 +177,6 @@ static void ttm_bo_man_put_node(struct ttm_mem_type_manager *man,
|
|||
struct ttm_mem_reg *mem)
|
||||
{
|
||||
mem->mm_node = (void *)NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
static int ttm_bo_man_init(struct ttm_mem_type_manager *man,
|
||||
|
@ -225,7 +224,7 @@ static int virtio_gpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
|
|||
man->default_caching = TTM_PL_FLAG_CACHED;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
|
||||
DRM_ERROR("Unsupported memory type %u\n", (unsigned int)type);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
|
@ -244,7 +243,6 @@ static void virtio_gpu_evict_flags(struct ttm_buffer_object *bo,
|
|||
placement->busy_placement = &placements;
|
||||
placement->num_placement = 1;
|
||||
placement->num_busy_placement = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
static int virtio_gpu_verify_access(struct ttm_buffer_object *bo,
|
||||
|
|
|
@ -62,6 +62,7 @@ void virtio_gpu_ctrl_ack(struct virtqueue *vq)
|
|||
{
|
||||
struct drm_device *dev = vq->vdev->priv;
|
||||
struct virtio_gpu_device *vgdev = dev->dev_private;
|
||||
|
||||
schedule_work(&vgdev->ctrlq.dequeue_work);
|
||||
}
|
||||
|
||||
|
@ -69,6 +70,7 @@ void virtio_gpu_cursor_ack(struct virtqueue *vq)
|
|||
{
|
||||
struct drm_device *dev = vq->vdev->priv;
|
||||
struct virtio_gpu_device *vgdev = dev->dev_private;
|
||||
|
||||
schedule_work(&vgdev->cursorq.dequeue_work);
|
||||
}
|
||||
|
||||
|
@ -272,7 +274,7 @@ static int virtio_gpu_queue_ctrl_buffer_locked(struct virtio_gpu_device *vgdev,
|
|||
return -ENODEV;
|
||||
|
||||
sg_init_one(&vcmd, vbuf->buf, vbuf->size);
|
||||
sgs[outcnt+incnt] = &vcmd;
|
||||
sgs[outcnt + incnt] = &vcmd;
|
||||
outcnt++;
|
||||
|
||||
if (vbuf->data_size) {
|
||||
|
@ -381,7 +383,8 @@ retry:
|
|||
}
|
||||
|
||||
/* just create gem objects for userspace and long lived objects,
|
||||
just use dma_alloced pages for the queue objects? */
|
||||
* just use dma_alloced pages for the queue objects?
|
||||
*/
|
||||
|
||||
/* create a basic resource */
|
||||
void virtio_gpu_cmd_create_resource(struct virtio_gpu_device *vgdev,
|
||||
|
@ -593,7 +596,6 @@ static void virtio_gpu_cmd_capset_cb(struct virtio_gpu_device *vgdev,
|
|||
wake_up(&vgdev->resp_wq);
|
||||
}
|
||||
|
||||
|
||||
int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev)
|
||||
{
|
||||
struct virtio_gpu_ctrl_hdr *cmd_p;
|
||||
|
@ -707,8 +709,8 @@ void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id,
|
|||
cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_CREATE);
|
||||
cmd_p->hdr.ctx_id = cpu_to_le32(id);
|
||||
cmd_p->nlen = cpu_to_le32(nlen);
|
||||
strncpy(cmd_p->debug_name, name, sizeof(cmd_p->debug_name)-1);
|
||||
cmd_p->debug_name[sizeof(cmd_p->debug_name)-1] = 0;
|
||||
strncpy(cmd_p->debug_name, name, sizeof(cmd_p->debug_name) - 1);
|
||||
cmd_p->debug_name[sizeof(cmd_p->debug_name) - 1] = 0;
|
||||
virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
|
||||
}
|
||||
|
||||
|
@ -852,6 +854,7 @@ int virtio_gpu_object_attach(struct virtio_gpu_device *vgdev,
|
|||
|
||||
if (!obj->pages) {
|
||||
int ret;
|
||||
|
||||
ret = virtio_gpu_object_get_sg_table(vgdev, obj);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
@ -443,17 +443,12 @@ int vmw_du_primary_plane_atomic_check(struct drm_plane *plane,
|
|||
{
|
||||
struct drm_crtc_state *crtc_state = NULL;
|
||||
struct drm_framebuffer *new_fb = state->fb;
|
||||
struct drm_rect clip = {};
|
||||
int ret;
|
||||
|
||||
if (state->crtc)
|
||||
crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc);
|
||||
|
||||
if (crtc_state && crtc_state->enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
|
||||
ret = drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
false, true);
|
||||
|
|
|
@ -55,7 +55,6 @@ static int zx_vl_plane_atomic_check(struct drm_plane *plane,
|
|||
struct drm_framebuffer *fb = plane_state->fb;
|
||||
struct drm_crtc *crtc = plane_state->crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_rect clip = {};
|
||||
int min_scale = FRAC_16_16(1, 8);
|
||||
int max_scale = FRAC_16_16(8, 1);
|
||||
|
||||
|
@ -75,12 +74,8 @@ static int zx_vl_plane_atomic_check(struct drm_plane *plane,
|
|||
if (!plane_state->crtc)
|
||||
return -EINVAL;
|
||||
|
||||
if (crtc_state->enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
|
||||
&clip, min_scale, max_scale,
|
||||
min_scale, max_scale,
|
||||
true, true);
|
||||
}
|
||||
|
||||
|
@ -291,7 +286,6 @@ static int zx_gl_plane_atomic_check(struct drm_plane *plane,
|
|||
struct drm_framebuffer *fb = plane_state->fb;
|
||||
struct drm_crtc *crtc = plane_state->crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_rect clip = {};
|
||||
|
||||
if (!crtc || !fb)
|
||||
return 0;
|
||||
|
@ -309,12 +303,7 @@ static int zx_gl_plane_atomic_check(struct drm_plane *plane,
|
|||
if (!plane_state->crtc)
|
||||
return -EINVAL;
|
||||
|
||||
if (crtc_state->enable)
|
||||
drm_mode_get_hv_timing(&crtc_state->mode,
|
||||
&clip.x2, &clip.y2);
|
||||
|
||||
return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
|
||||
&clip,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
false, true);
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include <drm/drm_crtc.h>
|
||||
|
||||
struct analogix_dp_device;
|
||||
|
||||
enum analogix_dp_devtype {
|
||||
EXYNOS_DP,
|
||||
RK3288_DP,
|
||||
|
@ -29,6 +31,7 @@ struct analogix_dp_plat_data {
|
|||
struct drm_panel *panel;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_connector *connector;
|
||||
bool skip_connector;
|
||||
|
||||
int (*power_on)(struct analogix_dp_plat_data *);
|
||||
int (*power_off)(struct analogix_dp_plat_data *);
|
||||
|
@ -38,16 +41,17 @@ struct analogix_dp_plat_data {
|
|||
struct drm_connector *);
|
||||
};
|
||||
|
||||
int analogix_dp_psr_supported(struct device *dev);
|
||||
int analogix_dp_enable_psr(struct device *dev);
|
||||
int analogix_dp_disable_psr(struct device *dev);
|
||||
int analogix_dp_psr_supported(struct analogix_dp_device *dp);
|
||||
int analogix_dp_enable_psr(struct analogix_dp_device *dp);
|
||||
int analogix_dp_disable_psr(struct analogix_dp_device *dp);
|
||||
|
||||
int analogix_dp_resume(struct device *dev);
|
||||
int analogix_dp_suspend(struct device *dev);
|
||||
int analogix_dp_resume(struct analogix_dp_device *dp);
|
||||
int analogix_dp_suspend(struct analogix_dp_device *dp);
|
||||
|
||||
int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
|
||||
struct analogix_dp_plat_data *plat_data);
|
||||
void analogix_dp_unbind(struct device *dev, struct device *master, void *data);
|
||||
struct analogix_dp_device *
|
||||
analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
|
||||
struct analogix_dp_plat_data *plat_data);
|
||||
void analogix_dp_unbind(struct analogix_dp_device *dp);
|
||||
|
||||
int analogix_dp_start_crc(struct drm_connector *connector);
|
||||
int analogix_dp_stop_crc(struct drm_connector *connector);
|
||||
|
|
|
@ -753,6 +753,28 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
|
|||
(old_plane_state) = (__state)->planes[__i].old_state,\
|
||||
(new_plane_state) = (__state)->planes[__i].new_state, 1))
|
||||
|
||||
/**
|
||||
* for_each_oldnew_plane_in_state_reverse - iterate over all planes in an atomic
|
||||
* update in reverse order
|
||||
* @__state: &struct drm_atomic_state pointer
|
||||
* @plane: &struct drm_plane iteration cursor
|
||||
* @old_plane_state: &struct drm_plane_state iteration cursor for the old state
|
||||
* @new_plane_state: &struct drm_plane_state iteration cursor for the new state
|
||||
* @__i: int iteration cursor, for macro-internal use
|
||||
*
|
||||
* This iterates over all planes in an atomic update in reverse order,
|
||||
* tracking both old and new state. This is useful in places where the
|
||||
* state delta needs to be considered, for example in atomic check functions.
|
||||
*/
|
||||
#define for_each_oldnew_plane_in_state_reverse(__state, plane, old_plane_state, new_plane_state, __i) \
|
||||
for ((__i) = ((__state)->dev->mode_config.num_total_plane - 1); \
|
||||
(__i) >= 0; \
|
||||
(__i)--) \
|
||||
for_each_if ((__state)->planes[__i].ptr && \
|
||||
((plane) = (__state)->planes[__i].ptr, \
|
||||
(old_plane_state) = (__state)->planes[__i].old_state,\
|
||||
(new_plane_state) = (__state)->planes[__i].new_state, 1))
|
||||
|
||||
/**
|
||||
* for_each_old_plane_in_state - iterate over all planes in an atomic update
|
||||
* @__state: &struct drm_atomic_state pointer
|
||||
|
|
|
@ -40,7 +40,6 @@ int drm_atomic_helper_check_modeset(struct drm_device *dev,
|
|||
struct drm_atomic_state *state);
|
||||
int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
|
||||
const struct drm_crtc_state *crtc_state,
|
||||
const struct drm_rect *clip,
|
||||
int min_scale,
|
||||
int max_scale,
|
||||
bool can_position,
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/ctype.h>
|
||||
|
||||
struct drm_crtc;
|
||||
struct drm_plane;
|
||||
|
||||
uint32_t drm_color_lut_extract(uint32_t user_input, uint32_t bit_precision);
|
||||
|
||||
|
@ -37,4 +38,22 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
|
|||
int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
|
||||
int gamma_size);
|
||||
|
||||
enum drm_color_encoding {
|
||||
DRM_COLOR_YCBCR_BT601,
|
||||
DRM_COLOR_YCBCR_BT709,
|
||||
DRM_COLOR_YCBCR_BT2020,
|
||||
DRM_COLOR_ENCODING_MAX,
|
||||
};
|
||||
|
||||
enum drm_color_range {
|
||||
DRM_COLOR_YCBCR_LIMITED_RANGE,
|
||||
DRM_COLOR_YCBCR_FULL_RANGE,
|
||||
DRM_COLOR_RANGE_MAX,
|
||||
};
|
||||
|
||||
int drm_plane_create_color_properties(struct drm_plane *plane,
|
||||
u32 supported_encodings,
|
||||
u32 supported_ranges,
|
||||
enum drm_color_encoding default_encoding,
|
||||
enum drm_color_range default_range);
|
||||
#endif
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/list.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <drm/drm_mode_object.h>
|
||||
#include <drm/drm_color_mgmt.h>
|
||||
|
||||
struct drm_crtc;
|
||||
struct drm_printer;
|
||||
|
@ -112,6 +113,20 @@ struct drm_plane_state {
|
|||
unsigned int zpos;
|
||||
unsigned int normalized_zpos;
|
||||
|
||||
/**
|
||||
* @color_encoding:
|
||||
*
|
||||
* Color encoding for non RGB formats
|
||||
*/
|
||||
enum drm_color_encoding color_encoding;
|
||||
|
||||
/**
|
||||
* @color_range:
|
||||
*
|
||||
* Color range for non RGB formats
|
||||
*/
|
||||
enum drm_color_range color_range;
|
||||
|
||||
/* Clipped coordinates */
|
||||
struct drm_rect src, dst;
|
||||
|
||||
|
@ -558,6 +573,23 @@ struct drm_plane {
|
|||
|
||||
struct drm_property *zpos_property;
|
||||
struct drm_property *rotation_property;
|
||||
|
||||
/**
|
||||
* @color_encoding_property:
|
||||
*
|
||||
* Optional "COLOR_ENCODING" enum property for specifying
|
||||
* color encoding for non RGB formats.
|
||||
* See drm_plane_create_color_properties().
|
||||
*/
|
||||
struct drm_property *color_encoding_property;
|
||||
/**
|
||||
* @color_range_property:
|
||||
*
|
||||
* Optional "COLOR_RANGE" enum property for specifying
|
||||
* color range for non RGB formats.
|
||||
* See drm_plane_create_color_properties().
|
||||
*/
|
||||
struct drm_property *color_range_property;
|
||||
};
|
||||
|
||||
#define obj_to_plane(x) container_of(x, struct drm_plane, base)
|
||||
|
|
|
@ -43,7 +43,6 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
|
|||
struct drm_framebuffer *fb,
|
||||
struct drm_rect *src,
|
||||
struct drm_rect *dest,
|
||||
const struct drm_rect *clip,
|
||||
unsigned int rotation,
|
||||
int min_scale,
|
||||
int max_scale,
|
||||
|
|
|
@ -237,27 +237,29 @@ static inline bool drm_property_type_is(struct drm_property *property,
|
|||
return property->flags & type;
|
||||
}
|
||||
|
||||
struct drm_property *drm_property_create(struct drm_device *dev, int flags,
|
||||
const char *name, int num_values);
|
||||
struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
|
||||
const char *name,
|
||||
struct drm_property *drm_property_create(struct drm_device *dev,
|
||||
u32 flags, const char *name,
|
||||
int num_values);
|
||||
struct drm_property *drm_property_create_enum(struct drm_device *dev,
|
||||
u32 flags, const char *name,
|
||||
const struct drm_prop_enum_list *props,
|
||||
int num_values);
|
||||
struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
|
||||
int flags, const char *name,
|
||||
u32 flags, const char *name,
|
||||
const struct drm_prop_enum_list *props,
|
||||
int num_props,
|
||||
uint64_t supported_bits);
|
||||
struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
|
||||
const char *name,
|
||||
struct drm_property *drm_property_create_range(struct drm_device *dev,
|
||||
u32 flags, const char *name,
|
||||
uint64_t min, uint64_t max);
|
||||
struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
|
||||
int flags, const char *name,
|
||||
u32 flags, const char *name,
|
||||
int64_t min, int64_t max);
|
||||
struct drm_property *drm_property_create_object(struct drm_device *dev,
|
||||
int flags, const char *name, uint32_t type);
|
||||
struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
|
||||
const char *name);
|
||||
u32 flags, const char *name,
|
||||
uint32_t type);
|
||||
struct drm_property *drm_property_create_bool(struct drm_device *dev,
|
||||
u32 flags, const char *name);
|
||||
int drm_property_add_enum(struct drm_property *property, int index,
|
||||
uint64_t value, const char *name);
|
||||
void drm_property_destroy(struct drm_device *dev, struct drm_property *property);
|
||||
|
|
|
@ -24,9 +24,30 @@ struct drm_simple_display_pipe_funcs {
|
|||
/**
|
||||
* @mode_valid:
|
||||
*
|
||||
* This function is called to filter out valid modes from the
|
||||
* suggestions suggested by the bridge or display. This optional
|
||||
* hook is passed in when initializing the pipeline.
|
||||
* This callback is used to check if a specific mode is valid in the
|
||||
* crtc used in this simple display pipe. This should be implemented
|
||||
* if the display pipe has some sort of restriction in the modes
|
||||
* it can display. For example, a given display pipe may be responsible
|
||||
* to set a clock value. If the clock can not produce all the values
|
||||
* for the available modes then this callback can be used to restrict
|
||||
* the number of modes to only the ones that can be displayed. Another
|
||||
* reason can be bandwidth mitigation: the memory port on the display
|
||||
* controller can have bandwidth limitations not allowing pixel data
|
||||
* to be fetched at any rate.
|
||||
*
|
||||
* This hook is used by the probe helpers to filter the mode list in
|
||||
* drm_helper_probe_single_connector_modes(), and it is used by the
|
||||
* atomic helpers to validate modes supplied by userspace in
|
||||
* drm_atomic_helper_check_modeset().
|
||||
*
|
||||
* This function is optional.
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* Since this function is both called from the check phase of an atomic
|
||||
* commit, and the mode validation in the probe paths it is not allowed
|
||||
* to look at anything else but the passed-in mode, and validate it
|
||||
* against configuration-invariant hardware constraints.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
|
@ -107,6 +128,24 @@ struct drm_simple_display_pipe_funcs {
|
|||
*/
|
||||
void (*cleanup_fb)(struct drm_simple_display_pipe *pipe,
|
||||
struct drm_plane_state *plane_state);
|
||||
|
||||
/**
|
||||
* @enable_vblank:
|
||||
*
|
||||
* Optional, called by &drm_crtc_funcs.enable_vblank. Please read
|
||||
* the documentation for the &drm_crtc_funcs.enable_vblank hook for
|
||||
* more details.
|
||||
*/
|
||||
int (*enable_vblank)(struct drm_simple_display_pipe *pipe);
|
||||
|
||||
/**
|
||||
* @disable_vblank:
|
||||
*
|
||||
* Optional, called by &drm_crtc_funcs.disable_vblank. Please read
|
||||
* the documentation for the &drm_crtc_funcs.disable_vblank hook for
|
||||
* more details.
|
||||
*/
|
||||
void (*disable_vblank)(struct drm_simple_display_pipe *pipe);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -363,7 +363,7 @@ struct drm_mode_get_connector {
|
|||
__u32 pad;
|
||||
};
|
||||
|
||||
#define DRM_MODE_PROP_PENDING (1<<0)
|
||||
#define DRM_MODE_PROP_PENDING (1<<0) /* deprecated, do not use */
|
||||
#define DRM_MODE_PROP_RANGE (1<<1)
|
||||
#define DRM_MODE_PROP_IMMUTABLE (1<<2)
|
||||
#define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */
|
||||
|
@ -598,8 +598,11 @@ struct drm_mode_crtc_lut {
|
|||
};
|
||||
|
||||
struct drm_color_ctm {
|
||||
/* Conversion matrix in S31.32 format. */
|
||||
__s64 matrix[9];
|
||||
/*
|
||||
* Conversion matrix in S31.32 sign-magnitude
|
||||
* (not two's complement!) format.
|
||||
*/
|
||||
__u64 matrix[9];
|
||||
};
|
||||
|
||||
struct drm_color_lut {
|
||||
|
|
Loading…
Reference in New Issue