Merge branch 'drm-misc-fixes' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes
(I've pulled from a non-tag to get the ttm regression fix) drm-misc-fixes-2021-02-10: * dp_mst: Don't report un-attached ports as connected * sun4i: tcon1 sync polarity fix; Always set HDMI clock rate; Fix H6 HDMI PHY config; Fix H6 max frequency * vc4: Fix buffer overflow * xlnx: Fix memory leak * ttm: page pool regression fix. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/YCPo6g3gDxD3P//h@linux-uq9g
This commit is contained in:
commit
551c81853d
@ -4224,6 +4224,7 @@ drm_dp_mst_detect_port(struct drm_connector *connector,
|
||||
|
||||
switch (port->pdt) {
|
||||
case DP_PEER_DEVICE_NONE:
|
||||
break;
|
||||
case DP_PEER_DEVICE_MST_BRANCHING:
|
||||
if (!port->mcs)
|
||||
ret = connector_status_connected;
|
||||
|
@ -689,6 +689,30 @@ static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
|
||||
SUN4I_TCON1_BASIC5_V_SYNC(vsync) |
|
||||
SUN4I_TCON1_BASIC5_H_SYNC(hsync));
|
||||
|
||||
/* Setup the polarity of multiple signals */
|
||||
if (tcon->quirks->polarity_in_ch0) {
|
||||
val = 0;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_PHSYNC)
|
||||
val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
|
||||
|
||||
regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, val);
|
||||
} else {
|
||||
/* according to vendor driver, this bit must be always set */
|
||||
val = SUN4I_TCON1_IO_POL_UNKNOWN;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_PHSYNC)
|
||||
val |= SUN4I_TCON1_IO_POL_HSYNC_POSITIVE;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
val |= SUN4I_TCON1_IO_POL_VSYNC_POSITIVE;
|
||||
|
||||
regmap_write(tcon->regs, SUN4I_TCON1_IO_POL_REG, val);
|
||||
}
|
||||
|
||||
/* Map output pins to channel 1 */
|
||||
regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
|
||||
SUN4I_TCON_GCTL_IOMAP_MASK,
|
||||
@ -1517,6 +1541,7 @@ static const struct sun4i_tcon_quirks sun8i_a83t_tv_quirks = {
|
||||
|
||||
static const struct sun4i_tcon_quirks sun8i_r40_tv_quirks = {
|
||||
.has_channel_1 = true,
|
||||
.polarity_in_ch0 = true,
|
||||
.set_mux = sun8i_r40_tcon_tv_set_mux,
|
||||
};
|
||||
|
||||
|
@ -153,6 +153,11 @@
|
||||
#define SUN4I_TCON1_BASIC5_V_SYNC(height) (((height) - 1) & 0x3ff)
|
||||
|
||||
#define SUN4I_TCON1_IO_POL_REG 0xf0
|
||||
/* there is no documentation about this bit */
|
||||
#define SUN4I_TCON1_IO_POL_UNKNOWN BIT(26)
|
||||
#define SUN4I_TCON1_IO_POL_HSYNC_POSITIVE BIT(25)
|
||||
#define SUN4I_TCON1_IO_POL_VSYNC_POSITIVE BIT(24)
|
||||
|
||||
#define SUN4I_TCON1_IO_TRI_REG 0xf4
|
||||
|
||||
#define SUN4I_TCON_ECC_FIFO_REG 0xf8
|
||||
@ -235,6 +240,7 @@ struct sun4i_tcon_quirks {
|
||||
bool needs_de_be_mux; /* sun6i needs mux to select backend */
|
||||
bool needs_edp_reset; /* a80 edp reset needed for tcon0 access */
|
||||
bool supports_lvds; /* Does the TCON support an LVDS output? */
|
||||
bool polarity_in_ch0; /* some tcon1 channels have polarity bits in tcon0 pol register */
|
||||
u8 dclk_min_div; /* minimum divider for TCON0 DCLK */
|
||||
|
||||
/* callback to handle tcon muxing options */
|
||||
|
@ -21,8 +21,7 @@ static void sun8i_dw_hdmi_encoder_mode_set(struct drm_encoder *encoder,
|
||||
{
|
||||
struct sun8i_dw_hdmi *hdmi = encoder_to_sun8i_dw_hdmi(encoder);
|
||||
|
||||
if (hdmi->quirks->set_rate)
|
||||
clk_set_rate(hdmi->clk_tmds, mode->crtc_clock * 1000);
|
||||
clk_set_rate(hdmi->clk_tmds, mode->crtc_clock * 1000);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs
|
||||
@ -48,11 +47,9 @@ sun8i_dw_hdmi_mode_valid_h6(struct dw_hdmi *hdmi, void *data,
|
||||
{
|
||||
/*
|
||||
* Controller support maximum of 594 MHz, which correlates to
|
||||
* 4K@60Hz 4:4:4 or RGB. However, for frequencies greater than
|
||||
* 340 MHz scrambling has to be enabled. Because scrambling is
|
||||
* not yet implemented, just limit to 340 MHz for now.
|
||||
* 4K@60Hz 4:4:4 or RGB.
|
||||
*/
|
||||
if (mode->clock > 340000)
|
||||
if (mode->clock > 594000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
return MODE_OK;
|
||||
@ -295,7 +292,6 @@ static int sun8i_dw_hdmi_remove(struct platform_device *pdev)
|
||||
|
||||
static const struct sun8i_dw_hdmi_quirks sun8i_a83t_quirks = {
|
||||
.mode_valid = sun8i_dw_hdmi_mode_valid_a83t,
|
||||
.set_rate = true,
|
||||
};
|
||||
|
||||
static const struct sun8i_dw_hdmi_quirks sun50i_h6_quirks = {
|
||||
|
@ -179,7 +179,6 @@ struct sun8i_dw_hdmi_quirks {
|
||||
enum drm_mode_status (*mode_valid)(struct dw_hdmi *hdmi, void *data,
|
||||
const struct drm_display_info *info,
|
||||
const struct drm_display_mode *mode);
|
||||
unsigned int set_rate : 1;
|
||||
unsigned int use_drm_infoframe : 1;
|
||||
};
|
||||
|
||||
|
@ -104,29 +104,21 @@ static const struct dw_hdmi_mpll_config sun50i_h6_mpll_cfg[] = {
|
||||
|
||||
static const struct dw_hdmi_curr_ctrl sun50i_h6_cur_ctr[] = {
|
||||
/* pixelclk bpp8 bpp10 bpp12 */
|
||||
{ 25175000, { 0x0000, 0x0000, 0x0000 }, },
|
||||
{ 27000000, { 0x0012, 0x0000, 0x0000 }, },
|
||||
{ 59400000, { 0x0008, 0x0008, 0x0008 }, },
|
||||
{ 72000000, { 0x0008, 0x0008, 0x001b }, },
|
||||
{ 74250000, { 0x0013, 0x0013, 0x0013 }, },
|
||||
{ 90000000, { 0x0008, 0x001a, 0x001b }, },
|
||||
{ 118800000, { 0x001b, 0x001a, 0x001b }, },
|
||||
{ 144000000, { 0x001b, 0x001a, 0x0034 }, },
|
||||
{ 180000000, { 0x001b, 0x0033, 0x0034 }, },
|
||||
{ 216000000, { 0x0036, 0x0033, 0x0034 }, },
|
||||
{ 237600000, { 0x0036, 0x0033, 0x001b }, },
|
||||
{ 288000000, { 0x0036, 0x001b, 0x001b }, },
|
||||
{ 297000000, { 0x0019, 0x001b, 0x0019 }, },
|
||||
{ 330000000, { 0x0036, 0x001b, 0x001b }, },
|
||||
{ 594000000, { 0x003f, 0x001b, 0x001b }, },
|
||||
{ 74250000, { 0x0013, 0x001a, 0x001b }, },
|
||||
{ 148500000, { 0x0019, 0x0033, 0x0034 }, },
|
||||
{ 297000000, { 0x0019, 0x001b, 0x001b }, },
|
||||
{ 594000000, { 0x0010, 0x001b, 0x001b }, },
|
||||
{ ~0UL, { 0x0000, 0x0000, 0x0000 }, }
|
||||
};
|
||||
|
||||
static const struct dw_hdmi_phy_config sun50i_h6_phy_config[] = {
|
||||
/*pixelclk symbol term vlev*/
|
||||
{ 74250000, 0x8009, 0x0004, 0x0232},
|
||||
{ 148500000, 0x8029, 0x0004, 0x0273},
|
||||
{ 594000000, 0x8039, 0x0004, 0x014a},
|
||||
{ 27000000, 0x8009, 0x0007, 0x02b0 },
|
||||
{ 74250000, 0x8009, 0x0006, 0x022d },
|
||||
{ 148500000, 0x8029, 0x0006, 0x0270 },
|
||||
{ 297000000, 0x8039, 0x0005, 0x01ab },
|
||||
{ 594000000, 0x8029, 0x0000, 0x008a },
|
||||
{ ~0UL, 0x0000, 0x0000, 0x0000}
|
||||
};
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/highmem.h>
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
#include <asm/set_memory.h>
|
||||
@ -218,6 +219,15 @@ static void ttm_pool_unmap(struct ttm_pool *pool, dma_addr_t dma_addr,
|
||||
/* Give pages into a specific pool_type */
|
||||
static void ttm_pool_type_give(struct ttm_pool_type *pt, struct page *p)
|
||||
{
|
||||
unsigned int i, num_pages = 1 << pt->order;
|
||||
|
||||
for (i = 0; i < num_pages; ++i) {
|
||||
if (PageHighMem(p))
|
||||
clear_highpage(p + i);
|
||||
else
|
||||
clear_page(page_address(p + i));
|
||||
}
|
||||
|
||||
spin_lock(&pt->lock);
|
||||
list_add(&p->lru, &pt->pages);
|
||||
spin_unlock(&pt->lock);
|
||||
|
@ -220,7 +220,7 @@ static void vc4_plane_reset(struct drm_plane *plane)
|
||||
__drm_atomic_helper_plane_reset(plane, &vc4_state->base);
|
||||
}
|
||||
|
||||
static void vc4_dlist_write(struct vc4_plane_state *vc4_state, u32 val)
|
||||
static void vc4_dlist_counter_increment(struct vc4_plane_state *vc4_state)
|
||||
{
|
||||
if (vc4_state->dlist_count == vc4_state->dlist_size) {
|
||||
u32 new_size = max(4u, vc4_state->dlist_count * 2);
|
||||
@ -235,7 +235,15 @@ static void vc4_dlist_write(struct vc4_plane_state *vc4_state, u32 val)
|
||||
vc4_state->dlist_size = new_size;
|
||||
}
|
||||
|
||||
vc4_state->dlist[vc4_state->dlist_count++] = val;
|
||||
vc4_state->dlist_count++;
|
||||
}
|
||||
|
||||
static void vc4_dlist_write(struct vc4_plane_state *vc4_state, u32 val)
|
||||
{
|
||||
unsigned int idx = vc4_state->dlist_count;
|
||||
|
||||
vc4_dlist_counter_increment(vc4_state);
|
||||
vc4_state->dlist[idx] = val;
|
||||
}
|
||||
|
||||
/* Returns the scl0/scl1 field based on whether the dimensions need to
|
||||
@ -978,8 +986,10 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
|
||||
* be set when calling vc4_plane_allocate_lbm().
|
||||
*/
|
||||
if (vc4_state->y_scaling[0] != VC4_SCALING_NONE ||
|
||||
vc4_state->y_scaling[1] != VC4_SCALING_NONE)
|
||||
vc4_state->lbm_offset = vc4_state->dlist_count++;
|
||||
vc4_state->y_scaling[1] != VC4_SCALING_NONE) {
|
||||
vc4_state->lbm_offset = vc4_state->dlist_count;
|
||||
vc4_dlist_counter_increment(vc4_state);
|
||||
}
|
||||
|
||||
if (num_planes > 1) {
|
||||
/* Emit Cb/Cr as channel 0 and Y as channel
|
||||
|
@ -1396,19 +1396,11 @@ static void zynqmp_disp_enable(struct zynqmp_disp *disp)
|
||||
*/
|
||||
static void zynqmp_disp_disable(struct zynqmp_disp *disp)
|
||||
{
|
||||
struct drm_crtc *crtc = &disp->crtc;
|
||||
|
||||
zynqmp_disp_audio_disable(&disp->audio);
|
||||
|
||||
zynqmp_disp_avbuf_disable_audio(&disp->avbuf);
|
||||
zynqmp_disp_avbuf_disable_channels(&disp->avbuf);
|
||||
zynqmp_disp_avbuf_disable(&disp->avbuf);
|
||||
|
||||
/* Mark the flip is done as crtc is disabled anyway */
|
||||
if (crtc->state->event) {
|
||||
complete_all(crtc->state->event->base.completion);
|
||||
crtc->state->event = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct zynqmp_disp *crtc_to_disp(struct drm_crtc *crtc)
|
||||
@ -1499,6 +1491,13 @@ zynqmp_disp_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
|
||||
drm_crtc_vblank_off(&disp->crtc);
|
||||
|
||||
spin_lock_irq(&crtc->dev->event_lock);
|
||||
if (crtc->state->event) {
|
||||
drm_crtc_send_vblank_event(crtc, crtc->state->event);
|
||||
crtc->state->event = NULL;
|
||||
}
|
||||
spin_unlock_irq(&crtc->dev->event_lock);
|
||||
|
||||
clk_disable_unprepare(disp->pclk);
|
||||
pm_runtime_put_sync(disp->dev);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user