mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-30 23:54:04 +08:00
drm i915, amd, dw-hdmi, omap, mediatek, tegra, udl fixes
-----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJcsAlJAAoJEAx081l5xIa+ZCgP/1a9/2Kb4wKEKg4WSQCuAZm+ mtCF2GvhN0bOk+XreUyXAboox1ldswB8woIb5pX6WjlzwRyYPT/7EKeLL4C1Fgtm gjFBCpJVeJJ3Vf0usMSSmXG3BNZaPIzjkZvVvDb5tMI78MjgUujzCcjAqCPRoQTC /wMK9qyX3mzQPrDhwF4ahc2O4gBSCQMT/xclnPDK2TJ3fJFIvWZHHBWCQgv+K9ty pDhqVGaR9YUn6bNjEt4l7Y5m4gK08kfB4ah/GRAYgkxKR3PmlJ0Mtd8S+niSJHk6 4Yt/Aw+wgrY/iO/Pt/2+e8/rGBQTMvR1km+urfYdG85jRb7xYbyZZpBIRhoSNhDZ QLDyPPRFVWjrqzCf+o25KfKP9Be1pwBGiQx/WZ6g403mohjbzrQq9lr7OA1VrkzQ LhRq2lzlLtEOWVMoXZx85OrFuI+EgMQglWIxhXoNqePUMj3MoFVFIypHupu7Z36X Onz19FJMaY225mGl5acdrQ8N8fYagympkp/TW5Lk6N8pnPWI0/gtGkJspKJALusP 9zJOU/iVQ5yXV5vXgYPLmAoNIwStn9sQvRsgKxa7z9FOWYoKSfO23V5N4y5gnH1f cTPDFe3twZD5r9kEgV+ovnfYJQ88C8LX1A//YVS7xj9tPZVDgkgWL4ZrpZGKH/ro OmQMQ7oG7+izulcbVcGP =6JCc -----END PGP SIGNATURE----- Merge tag 'drm-fixes-2019-04-12' of git://anongit.freedesktop.org/drm/drm Pull drm fixes from Dave Airlie: "Fixes across the driver spectrum this week, the mediatek fbdev support might be a bit late for this round, but I looked over it and it's not very large and seems like a useful feature for them. Otherwise the main thing is a regression fix for i915 5.0 bug that caused black screens on a bunch of Dell XPS 15s I think, I know at least Fedora is waiting for this to land, and the udl fix is also for a regression since 5.0 where unplugging the device would end badly. core: - make atomic hooks optional i915: - Revert a 5.0 regression where some eDP panels stopped working - DSI related fixes for platforms up to IceLake - GVT (regression fix, warning fix, use-after free fix) amdgpu: - Cursor fixes - missing PCI ID fix for KFD - XGMI fix - shadow buffer handling after reset fix udl: - fix unplugging device crashes. mediatek: - stabilise MT2701 HDMI support - fbdev support tegra: - fix for build regression in rc1. sun4i: - Allwinner A6 max freq improvements - null ptr deref fix dw-hdmi: - SCDC configuration improvements omap: - CEC clock management policy fix" * tag 'drm-fixes-2019-04-12' of git://anongit.freedesktop.org/drm/drm: (32 commits) gpu: host1x: Fix compile error when IOMMU API is not available drm/i915/gvt: Roundup fb->height into tile's height at calucation fb->size drm/i915/dp: revert back to max link rate and lane count on eDP drm/i915/icl: Fix port disable sequence for mipi-dsi drm/i915/icl: Ungate ddi clocks before IO enable drm/mediatek: no change parent rate in round_rate() for MT2701 hdmi phy drm/mediatek: using new factor for tvdpll for MT2701 hdmi phy drm/mediatek: remove flag CLK_SET_RATE_PARENT for MT2701 hdmi phy drm/mediatek: make implementation of recalc_rate() for MT2701 hdmi phy drm/mediatek: fix the rate and divder of hdmi phy for MT2701 drm/mediatek: fix possible object reference leak drm/i915: Get power refs in encoder->get_power_domains() drm/i915: Fix pipe_bpp readout for BXT/GLK DSI drm/amd/display: Fix negative cursor pos programming (v2) drm/sun4i: tcon top: Fix NULL/invalid pointer dereference in sun8i_tcon_top_un/bind drm/udl: add a release method and delay modeset teardown drm/i915/gvt: Prevent use-after-free in ppgtt_free_all_spt() drm/i915/gvt: Annotate iomem usage drm/sun4i: DW HDMI: Lower max. supported rate for H6 Revert "Documentation/gpu/meson: Remove link to meson_canvas.c" ...
This commit is contained in:
commit
58890f31f9
@ -3173,11 +3173,16 @@ static int amdgpu_device_recover_vram(struct amdgpu_device *adev)
|
||||
break;
|
||||
|
||||
if (fence) {
|
||||
r = dma_fence_wait_timeout(fence, false, tmo);
|
||||
tmo = dma_fence_wait_timeout(fence, false, tmo);
|
||||
dma_fence_put(fence);
|
||||
fence = next;
|
||||
if (r <= 0)
|
||||
if (tmo == 0) {
|
||||
r = -ETIMEDOUT;
|
||||
break;
|
||||
} else if (tmo < 0) {
|
||||
r = tmo;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
fence = next;
|
||||
}
|
||||
@ -3188,8 +3193,8 @@ static int amdgpu_device_recover_vram(struct amdgpu_device *adev)
|
||||
tmo = dma_fence_wait_timeout(fence, false, tmo);
|
||||
dma_fence_put(fence);
|
||||
|
||||
if (r <= 0 || tmo <= 0) {
|
||||
DRM_ERROR("recover vram bo from shadow failed\n");
|
||||
if (r < 0 || tmo <= 0) {
|
||||
DRM_ERROR("recover vram bo from shadow failed, r is %ld, tmo is %ld\n", r, tmo);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "amdgpu_trace.h"
|
||||
|
||||
#define AMDGPU_IB_TEST_TIMEOUT msecs_to_jiffies(1000)
|
||||
#define AMDGPU_IB_TEST_GFX_XGMI_TIMEOUT msecs_to_jiffies(2000)
|
||||
|
||||
/*
|
||||
* IB
|
||||
@ -344,6 +345,8 @@ int amdgpu_ib_ring_tests(struct amdgpu_device *adev)
|
||||
* cost waiting for it coming back under RUNTIME only
|
||||
*/
|
||||
tmo_gfx = 8 * AMDGPU_IB_TEST_TIMEOUT;
|
||||
} else if (adev->gmc.xgmi.hive_id) {
|
||||
tmo_gfx = AMDGPU_IB_TEST_GFX_XGMI_TIMEOUT;
|
||||
}
|
||||
|
||||
for (i = 0; i < adev->num_rings; ++i) {
|
||||
|
@ -320,6 +320,7 @@ static const struct kfd_deviceid supported_devices[] = {
|
||||
{ 0x9876, &carrizo_device_info }, /* Carrizo */
|
||||
{ 0x9877, &carrizo_device_info }, /* Carrizo */
|
||||
{ 0x15DD, &raven_device_info }, /* Raven */
|
||||
{ 0x15D8, &raven_device_info }, /* Raven */
|
||||
#endif
|
||||
{ 0x67A0, &hawaii_device_info }, /* Hawaii */
|
||||
{ 0x67A1, &hawaii_device_info }, /* Hawaii */
|
||||
|
@ -4533,6 +4533,7 @@ static void handle_cursor_update(struct drm_plane *plane,
|
||||
amdgpu_crtc->cursor_width = plane->state->crtc_w;
|
||||
amdgpu_crtc->cursor_height = plane->state->crtc_h;
|
||||
|
||||
memset(&attributes, 0, sizeof(attributes));
|
||||
attributes.address.high_part = upper_32_bits(address);
|
||||
attributes.address.low_part = lower_32_bits(address);
|
||||
attributes.width = plane->state->crtc_w;
|
||||
|
@ -1150,28 +1150,9 @@ void hubp1_cursor_set_position(
|
||||
REG_UPDATE(CURSOR_CONTROL,
|
||||
CURSOR_ENABLE, cur_en);
|
||||
|
||||
//account for cases where we see negative offset relative to overlay plane
|
||||
if (src_x_offset < 0 && src_y_offset < 0) {
|
||||
REG_SET_2(CURSOR_POSITION, 0,
|
||||
CURSOR_X_POSITION, 0,
|
||||
CURSOR_Y_POSITION, 0);
|
||||
x_hotspot -= src_x_offset;
|
||||
y_hotspot -= src_y_offset;
|
||||
} else if (src_x_offset < 0) {
|
||||
REG_SET_2(CURSOR_POSITION, 0,
|
||||
CURSOR_X_POSITION, 0,
|
||||
CURSOR_Y_POSITION, pos->y);
|
||||
x_hotspot -= src_x_offset;
|
||||
} else if (src_y_offset < 0) {
|
||||
REG_SET_2(CURSOR_POSITION, 0,
|
||||
REG_SET_2(CURSOR_POSITION, 0,
|
||||
CURSOR_X_POSITION, pos->x,
|
||||
CURSOR_Y_POSITION, 0);
|
||||
y_hotspot -= src_y_offset;
|
||||
} else {
|
||||
REG_SET_2(CURSOR_POSITION, 0,
|
||||
CURSOR_X_POSITION, pos->x,
|
||||
CURSOR_Y_POSITION, pos->y);
|
||||
}
|
||||
CURSOR_Y_POSITION, pos->y);
|
||||
|
||||
REG_SET_2(CURSOR_HOT_SPOT, 0,
|
||||
CURSOR_HOT_SPOT_X, x_hotspot,
|
||||
|
@ -1037,6 +1037,31 @@ void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write);
|
||||
|
||||
/* Filter out invalid setups to avoid configuring SCDC and scrambling */
|
||||
static bool dw_hdmi_support_scdc(struct dw_hdmi *hdmi)
|
||||
{
|
||||
struct drm_display_info *display = &hdmi->connector.display_info;
|
||||
|
||||
/* Completely disable SCDC support for older controllers */
|
||||
if (hdmi->version < 0x200a)
|
||||
return false;
|
||||
|
||||
/* Disable if SCDC is not supported, or if an HF-VSDB block is absent */
|
||||
if (!display->hdmi.scdc.supported ||
|
||||
!display->hdmi.scdc.scrambling.supported)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Disable if display only support low TMDS rates and scrambling
|
||||
* for low rates is not supported either
|
||||
*/
|
||||
if (!display->hdmi.scdc.scrambling.low_rates &&
|
||||
display->max_tmds_clock <= 340000)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* HDMI2.0 Specifies the following procedure for High TMDS Bit Rates:
|
||||
* - The Source shall suspend transmission of the TMDS clock and data
|
||||
@ -1055,7 +1080,7 @@ void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi)
|
||||
unsigned long mtmdsclock = hdmi->hdmi_data.video_mode.mtmdsclock;
|
||||
|
||||
/* Control for TMDS Bit Period/TMDS Clock-Period Ratio */
|
||||
if (hdmi->connector.display_info.hdmi.scdc.supported) {
|
||||
if (dw_hdmi_support_scdc(hdmi)) {
|
||||
if (mtmdsclock > HDMI14_MAX_TMDSCLK)
|
||||
drm_scdc_set_high_tmds_clock_ratio(hdmi->ddc, 1);
|
||||
else
|
||||
@ -1579,8 +1604,9 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||
|
||||
/* Set up HDMI_FC_INVIDCONF */
|
||||
inv_val = (hdmi->hdmi_data.hdcp_enable ||
|
||||
vmode->mtmdsclock > HDMI14_MAX_TMDSCLK ||
|
||||
hdmi_info->scdc.scrambling.low_rates ?
|
||||
(dw_hdmi_support_scdc(hdmi) &&
|
||||
(vmode->mtmdsclock > HDMI14_MAX_TMDSCLK ||
|
||||
hdmi_info->scdc.scrambling.low_rates)) ?
|
||||
HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE :
|
||||
HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE);
|
||||
|
||||
@ -1646,7 +1672,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
|
||||
}
|
||||
|
||||
/* Scrambling Control */
|
||||
if (hdmi_info->scdc.supported) {
|
||||
if (dw_hdmi_support_scdc(hdmi)) {
|
||||
if (vmode->mtmdsclock > HDMI14_MAX_TMDSCLK ||
|
||||
hdmi_info->scdc.scrambling.low_rates) {
|
||||
/*
|
||||
|
@ -1034,7 +1034,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
|
||||
funcs->atomic_disable(crtc, old_crtc_state);
|
||||
else if (funcs->disable)
|
||||
funcs->disable(crtc);
|
||||
else
|
||||
else if (funcs->dpms)
|
||||
funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
|
||||
|
||||
if (!(dev->irq_enabled && dev->num_crtcs))
|
||||
@ -1277,10 +1277,9 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
|
||||
if (new_crtc_state->enable) {
|
||||
DRM_DEBUG_ATOMIC("enabling [CRTC:%d:%s]\n",
|
||||
crtc->base.id, crtc->name);
|
||||
|
||||
if (funcs->atomic_enable)
|
||||
funcs->atomic_enable(crtc, old_crtc_state);
|
||||
else
|
||||
else if (funcs->commit)
|
||||
funcs->commit(crtc);
|
||||
}
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ static int vgpu_get_plane_info(struct drm_device *dev,
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct intel_vgpu_primary_plane_format p;
|
||||
struct intel_vgpu_cursor_plane_format c;
|
||||
int ret;
|
||||
int ret, tile_height = 1;
|
||||
|
||||
if (plane_id == DRM_PLANE_TYPE_PRIMARY) {
|
||||
ret = intel_vgpu_decode_primary_plane(vgpu, &p);
|
||||
@ -228,12 +228,15 @@ static int vgpu_get_plane_info(struct drm_device *dev,
|
||||
break;
|
||||
case PLANE_CTL_TILED_X:
|
||||
info->drm_format_mod = I915_FORMAT_MOD_X_TILED;
|
||||
tile_height = 8;
|
||||
break;
|
||||
case PLANE_CTL_TILED_Y:
|
||||
info->drm_format_mod = I915_FORMAT_MOD_Y_TILED;
|
||||
tile_height = 32;
|
||||
break;
|
||||
case PLANE_CTL_TILED_YF:
|
||||
info->drm_format_mod = I915_FORMAT_MOD_Yf_TILED;
|
||||
tile_height = 32;
|
||||
break;
|
||||
default:
|
||||
gvt_vgpu_err("invalid tiling mode: %x\n", p.tiled);
|
||||
@ -264,8 +267,8 @@ static int vgpu_get_plane_info(struct drm_device *dev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info->size = (info->stride * info->height + PAGE_SIZE - 1)
|
||||
>> PAGE_SHIFT;
|
||||
info->size = (info->stride * roundup(info->height, tile_height)
|
||||
+ PAGE_SIZE - 1) >> PAGE_SHIFT;
|
||||
if (info->size == 0) {
|
||||
gvt_vgpu_err("fb size is zero\n");
|
||||
return -EINVAL;
|
||||
|
@ -750,14 +750,20 @@ static void ppgtt_free_spt(struct intel_vgpu_ppgtt_spt *spt)
|
||||
|
||||
static void ppgtt_free_all_spt(struct intel_vgpu *vgpu)
|
||||
{
|
||||
struct intel_vgpu_ppgtt_spt *spt;
|
||||
struct intel_vgpu_ppgtt_spt *spt, *spn;
|
||||
struct radix_tree_iter iter;
|
||||
void **slot;
|
||||
LIST_HEAD(all_spt);
|
||||
void __rcu **slot;
|
||||
|
||||
rcu_read_lock();
|
||||
radix_tree_for_each_slot(slot, &vgpu->gtt.spt_tree, &iter, 0) {
|
||||
spt = radix_tree_deref_slot(slot);
|
||||
ppgtt_free_spt(spt);
|
||||
list_move(&spt->post_shadow_list, &all_spt);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
list_for_each_entry_safe(spt, spn, &all_spt, post_shadow_list)
|
||||
ppgtt_free_spt(spt);
|
||||
}
|
||||
|
||||
static int ppgtt_handle_guest_write_page_table_bytes(
|
||||
|
@ -905,7 +905,7 @@ static inline bool intel_vgpu_in_aperture(struct intel_vgpu *vgpu, u64 off)
|
||||
static int intel_vgpu_aperture_rw(struct intel_vgpu *vgpu, u64 off,
|
||||
void *buf, unsigned long count, bool is_write)
|
||||
{
|
||||
void *aperture_va;
|
||||
void __iomem *aperture_va;
|
||||
|
||||
if (!intel_vgpu_in_aperture(vgpu, off) ||
|
||||
!intel_vgpu_in_aperture(vgpu, off + count)) {
|
||||
@ -920,9 +920,9 @@ static int intel_vgpu_aperture_rw(struct intel_vgpu *vgpu, u64 off,
|
||||
return -EIO;
|
||||
|
||||
if (is_write)
|
||||
memcpy(aperture_va + offset_in_page(off), buf, count);
|
||||
memcpy_toio(aperture_va + offset_in_page(off), buf, count);
|
||||
else
|
||||
memcpy(buf, aperture_va + offset_in_page(off), count);
|
||||
memcpy_fromio(buf, aperture_va + offset_in_page(off), count);
|
||||
|
||||
io_mapping_unmap(aperture_va);
|
||||
|
||||
|
@ -323,6 +323,21 @@ static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder)
|
||||
}
|
||||
}
|
||||
|
||||
static void get_dsi_io_power_domains(struct drm_i915_private *dev_priv,
|
||||
struct intel_dsi *intel_dsi)
|
||||
{
|
||||
enum port port;
|
||||
|
||||
for_each_dsi_port(port, intel_dsi->ports) {
|
||||
WARN_ON(intel_dsi->io_wakeref[port]);
|
||||
intel_dsi->io_wakeref[port] =
|
||||
intel_display_power_get(dev_priv,
|
||||
port == PORT_A ?
|
||||
POWER_DOMAIN_PORT_DDI_A_IO :
|
||||
POWER_DOMAIN_PORT_DDI_B_IO);
|
||||
}
|
||||
}
|
||||
|
||||
static void gen11_dsi_enable_io_power(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
@ -336,13 +351,7 @@ static void gen11_dsi_enable_io_power(struct intel_encoder *encoder)
|
||||
I915_WRITE(ICL_DSI_IO_MODECTL(port), tmp);
|
||||
}
|
||||
|
||||
for_each_dsi_port(port, intel_dsi->ports) {
|
||||
intel_dsi->io_wakeref[port] =
|
||||
intel_display_power_get(dev_priv,
|
||||
port == PORT_A ?
|
||||
POWER_DOMAIN_PORT_DDI_A_IO :
|
||||
POWER_DOMAIN_PORT_DDI_B_IO);
|
||||
}
|
||||
get_dsi_io_power_domains(dev_priv, intel_dsi);
|
||||
}
|
||||
|
||||
static void gen11_dsi_power_up_lanes(struct intel_encoder *encoder)
|
||||
@ -589,6 +598,12 @@ static void gen11_dsi_map_pll(struct intel_encoder *encoder,
|
||||
val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, port);
|
||||
}
|
||||
I915_WRITE(DPCLKA_CFGCR0_ICL, val);
|
||||
|
||||
for_each_dsi_port(port, intel_dsi->ports) {
|
||||
val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port);
|
||||
}
|
||||
I915_WRITE(DPCLKA_CFGCR0_ICL, val);
|
||||
|
||||
POSTING_READ(DPCLKA_CFGCR0_ICL);
|
||||
|
||||
mutex_unlock(&dev_priv->dpll_lock);
|
||||
@ -1117,7 +1132,7 @@ static void gen11_dsi_disable_port(struct intel_encoder *encoder)
|
||||
DRM_ERROR("DDI port:%c buffer not idle\n",
|
||||
port_name(port));
|
||||
}
|
||||
gen11_dsi_ungate_clocks(encoder);
|
||||
gen11_dsi_gate_clocks(encoder);
|
||||
}
|
||||
|
||||
static void gen11_dsi_disable_io_power(struct intel_encoder *encoder)
|
||||
@ -1218,20 +1233,11 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 gen11_dsi_get_power_domains(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *crtc_state)
|
||||
static void gen11_dsi_get_power_domains(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
||||
u64 domains = 0;
|
||||
enum port port;
|
||||
|
||||
for_each_dsi_port(port, intel_dsi->ports)
|
||||
if (port == PORT_A)
|
||||
domains |= BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO);
|
||||
else
|
||||
domains |= BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO);
|
||||
|
||||
return domains;
|
||||
get_dsi_io_power_domains(to_i915(encoder->base.dev),
|
||||
enc_to_intel_dsi(&encoder->base));
|
||||
}
|
||||
|
||||
static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
|
||||
|
@ -2075,12 +2075,11 @@ intel_ddi_main_link_aux_domain(struct intel_digital_port *dig_port)
|
||||
intel_aux_power_domain(dig_port);
|
||||
}
|
||||
|
||||
static u64 intel_ddi_get_power_domains(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *crtc_state)
|
||||
static void intel_ddi_get_power_domains(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_digital_port *dig_port;
|
||||
u64 domains;
|
||||
|
||||
/*
|
||||
* TODO: Add support for MST encoders. Atm, the following should never
|
||||
@ -2088,10 +2087,10 @@ static u64 intel_ddi_get_power_domains(struct intel_encoder *encoder,
|
||||
* hook.
|
||||
*/
|
||||
if (WARN_ON(intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)))
|
||||
return 0;
|
||||
return;
|
||||
|
||||
dig_port = enc_to_dig_port(&encoder->base);
|
||||
domains = BIT_ULL(dig_port->ddi_io_power_domain);
|
||||
intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain);
|
||||
|
||||
/*
|
||||
* AUX power is only needed for (e)DP mode, and for HDMI mode on TC
|
||||
@ -2099,15 +2098,15 @@ static u64 intel_ddi_get_power_domains(struct intel_encoder *encoder,
|
||||
*/
|
||||
if (intel_crtc_has_dp_encoder(crtc_state) ||
|
||||
intel_port_is_tc(dev_priv, encoder->port))
|
||||
domains |= BIT_ULL(intel_ddi_main_link_aux_domain(dig_port));
|
||||
intel_display_power_get(dev_priv,
|
||||
intel_ddi_main_link_aux_domain(dig_port));
|
||||
|
||||
/*
|
||||
* VDSC power is needed when DSC is enabled
|
||||
*/
|
||||
if (crtc_state->dsc_params.compression_enable)
|
||||
domains |= BIT_ULL(intel_dsc_power_domain(crtc_state));
|
||||
|
||||
return domains;
|
||||
intel_display_power_get(dev_priv,
|
||||
intel_dsc_power_domain(crtc_state));
|
||||
}
|
||||
|
||||
void intel_ddi_enable_pipe_clock(const struct intel_crtc_state *crtc_state)
|
||||
@ -2825,10 +2824,10 @@ void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder)
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* DSI ports should have their DDI clock ungated when disabled
|
||||
* and gated when enabled.
|
||||
* For DSI we keep the ddi clocks gated
|
||||
* except during enable/disable sequence.
|
||||
*/
|
||||
ddi_clk_needed = !encoder->base.crtc;
|
||||
ddi_clk_needed = false;
|
||||
}
|
||||
|
||||
val = I915_READ(DPCLKA_CFGCR0_ICL);
|
||||
|
@ -15986,8 +15986,6 @@ get_encoder_power_domains(struct drm_i915_private *dev_priv)
|
||||
struct intel_encoder *encoder;
|
||||
|
||||
for_each_intel_encoder(&dev_priv->drm, encoder) {
|
||||
u64 get_domains;
|
||||
enum intel_display_power_domain domain;
|
||||
struct intel_crtc_state *crtc_state;
|
||||
|
||||
if (!encoder->get_power_domains)
|
||||
@ -16001,9 +15999,7 @@ get_encoder_power_domains(struct drm_i915_private *dev_priv)
|
||||
continue;
|
||||
|
||||
crtc_state = to_intel_crtc_state(encoder->base.crtc->state);
|
||||
get_domains = encoder->get_power_domains(encoder, crtc_state);
|
||||
for_each_power_domain(domain, get_domains)
|
||||
intel_display_power_get(dev_priv, domain);
|
||||
encoder->get_power_domains(encoder, crtc_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1859,42 +1859,6 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Optimize link config in order: max bpp, min lanes, min clock */
|
||||
static int
|
||||
intel_dp_compute_link_config_fast(struct intel_dp *intel_dp,
|
||||
struct intel_crtc_state *pipe_config,
|
||||
const struct link_config_limits *limits)
|
||||
{
|
||||
struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
|
||||
int bpp, clock, lane_count;
|
||||
int mode_rate, link_clock, link_avail;
|
||||
|
||||
for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) {
|
||||
mode_rate = intel_dp_link_required(adjusted_mode->crtc_clock,
|
||||
bpp);
|
||||
|
||||
for (lane_count = limits->min_lane_count;
|
||||
lane_count <= limits->max_lane_count;
|
||||
lane_count <<= 1) {
|
||||
for (clock = limits->min_clock; clock <= limits->max_clock; clock++) {
|
||||
link_clock = intel_dp->common_rates[clock];
|
||||
link_avail = intel_dp_max_data_rate(link_clock,
|
||||
lane_count);
|
||||
|
||||
if (mode_rate <= link_avail) {
|
||||
pipe_config->lane_count = lane_count;
|
||||
pipe_config->pipe_bpp = bpp;
|
||||
pipe_config->port_clock = link_clock;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc)
|
||||
{
|
||||
int i, num_bpc;
|
||||
@ -2031,15 +1995,13 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
|
||||
limits.min_bpp = 6 * 3;
|
||||
limits.max_bpp = intel_dp_compute_bpp(intel_dp, pipe_config);
|
||||
|
||||
if (intel_dp_is_edp(intel_dp) && intel_dp->edp_dpcd[0] < DP_EDP_14) {
|
||||
if (intel_dp_is_edp(intel_dp)) {
|
||||
/*
|
||||
* Use the maximum clock and number of lanes the eDP panel
|
||||
* advertizes being capable of. The eDP 1.3 and earlier panels
|
||||
* are generally designed to support only a single clock and
|
||||
* lane configuration, and typically these values correspond to
|
||||
* the native resolution of the panel. With eDP 1.4 rate select
|
||||
* and DSC, this is decreasingly the case, and we need to be
|
||||
* able to select less than maximum link config.
|
||||
* advertizes being capable of. The panels are generally
|
||||
* designed to support only a single clock and lane
|
||||
* configuration, and typically these values correspond to the
|
||||
* native resolution of the panel.
|
||||
*/
|
||||
limits.min_lane_count = limits.max_lane_count;
|
||||
limits.min_clock = limits.max_clock;
|
||||
@ -2053,22 +2015,11 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
|
||||
intel_dp->common_rates[limits.max_clock],
|
||||
limits.max_bpp, adjusted_mode->crtc_clock);
|
||||
|
||||
if (intel_dp_is_edp(intel_dp))
|
||||
/*
|
||||
* Optimize for fast and narrow. eDP 1.3 section 3.3 and eDP 1.4
|
||||
* section A.1: "It is recommended that the minimum number of
|
||||
* lanes be used, using the minimum link rate allowed for that
|
||||
* lane configuration."
|
||||
*
|
||||
* Note that we use the max clock and lane count for eDP 1.3 and
|
||||
* earlier, and fast vs. wide is irrelevant.
|
||||
*/
|
||||
ret = intel_dp_compute_link_config_fast(intel_dp, pipe_config,
|
||||
&limits);
|
||||
else
|
||||
/* Optimize for slow and wide. */
|
||||
ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config,
|
||||
&limits);
|
||||
/*
|
||||
* Optimize for slow and wide. This is the place to add alternative
|
||||
* optimization policy.
|
||||
*/
|
||||
ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config, &limits);
|
||||
|
||||
/* enable compression if the mode doesn't fit available BW */
|
||||
DRM_DEBUG_KMS("Force DSC en = %d\n", intel_dp->force_dsc_en);
|
||||
|
@ -270,10 +270,12 @@ struct intel_encoder {
|
||||
* be set correctly before calling this function. */
|
||||
void (*get_config)(struct intel_encoder *,
|
||||
struct intel_crtc_state *pipe_config);
|
||||
/* Returns a mask of power domains that need to be referenced as part
|
||||
* of the hardware state readout code. */
|
||||
u64 (*get_power_domains)(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *crtc_state);
|
||||
/*
|
||||
* Acquires the power domains needed for an active encoder during
|
||||
* hardware state readout.
|
||||
*/
|
||||
void (*get_power_domains)(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *crtc_state);
|
||||
/*
|
||||
* Called during system suspend after all pending requests for the
|
||||
* encoder are flushed (for example for DP AUX transactions) and
|
||||
|
@ -256,6 +256,28 @@ static void band_gap_reset(struct drm_i915_private *dev_priv)
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
}
|
||||
|
||||
static int bdw_get_pipemisc_bpp(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
u32 tmp;
|
||||
|
||||
tmp = I915_READ(PIPEMISC(crtc->pipe));
|
||||
|
||||
switch (tmp & PIPEMISC_DITHER_BPC_MASK) {
|
||||
case PIPEMISC_DITHER_6_BPC:
|
||||
return 18;
|
||||
case PIPEMISC_DITHER_8_BPC:
|
||||
return 24;
|
||||
case PIPEMISC_DITHER_10_BPC:
|
||||
return 30;
|
||||
case PIPEMISC_DITHER_12_BPC:
|
||||
return 36;
|
||||
default:
|
||||
MISSING_CASE(tmp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int intel_dsi_compute_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config,
|
||||
struct drm_connector_state *conn_state)
|
||||
@ -1071,6 +1093,8 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder,
|
||||
bpp = mipi_dsi_pixel_format_to_bpp(
|
||||
pixel_format_from_register_bits(fmt));
|
||||
|
||||
pipe_config->pipe_bpp = bdw_get_pipemisc_bpp(crtc);
|
||||
|
||||
/* Enable Frame time stamo based scanline reporting */
|
||||
adjusted_mode->private_flags |=
|
||||
I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP;
|
||||
|
@ -662,13 +662,11 @@ static unsigned int mt8173_calculate_factor(int clock)
|
||||
static unsigned int mt2701_calculate_factor(int clock)
|
||||
{
|
||||
if (clock <= 64000)
|
||||
return 16;
|
||||
else if (clock <= 128000)
|
||||
return 8;
|
||||
else if (clock <= 256000)
|
||||
return 4;
|
||||
else
|
||||
else if (clock <= 128000)
|
||||
return 2;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct mtk_dpi_conf mt8173_conf = {
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_of.h>
|
||||
@ -341,6 +342,8 @@ static struct drm_driver mtk_drm_driver = {
|
||||
.gem_prime_get_sg_table = mtk_gem_prime_get_sg_table,
|
||||
.gem_prime_import_sg_table = mtk_gem_prime_import_sg_table,
|
||||
.gem_prime_mmap = mtk_drm_gem_mmap_buf,
|
||||
.gem_prime_vmap = mtk_drm_gem_prime_vmap,
|
||||
.gem_prime_vunmap = mtk_drm_gem_prime_vunmap,
|
||||
.fops = &mtk_drm_fops,
|
||||
|
||||
.name = DRIVER_NAME,
|
||||
@ -376,6 +379,10 @@ static int mtk_drm_bind(struct device *dev)
|
||||
if (ret < 0)
|
||||
goto err_deinit;
|
||||
|
||||
ret = drm_fbdev_generic_setup(drm, 32);
|
||||
if (ret)
|
||||
DRM_ERROR("Failed to initialize fbdev: %d\n", ret);
|
||||
|
||||
return 0;
|
||||
|
||||
err_deinit:
|
||||
|
@ -241,3 +241,49 @@ err_gem_free:
|
||||
kfree(mtk_gem);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
void *mtk_drm_gem_prime_vmap(struct drm_gem_object *obj)
|
||||
{
|
||||
struct mtk_drm_gem_obj *mtk_gem = to_mtk_gem_obj(obj);
|
||||
struct sg_table *sgt;
|
||||
struct sg_page_iter iter;
|
||||
unsigned int npages;
|
||||
unsigned int i = 0;
|
||||
|
||||
if (mtk_gem->kvaddr)
|
||||
return mtk_gem->kvaddr;
|
||||
|
||||
sgt = mtk_gem_prime_get_sg_table(obj);
|
||||
if (IS_ERR(sgt))
|
||||
return NULL;
|
||||
|
||||
npages = obj->size >> PAGE_SHIFT;
|
||||
mtk_gem->pages = kcalloc(npages, sizeof(*mtk_gem->pages), GFP_KERNEL);
|
||||
if (!mtk_gem->pages)
|
||||
goto out;
|
||||
|
||||
for_each_sg_page(sgt->sgl, &iter, sgt->orig_nents, 0) {
|
||||
mtk_gem->pages[i++] = sg_page_iter_page(&iter);
|
||||
if (i > npages)
|
||||
break;
|
||||
}
|
||||
mtk_gem->kvaddr = vmap(mtk_gem->pages, npages, VM_MAP,
|
||||
pgprot_writecombine(PAGE_KERNEL));
|
||||
|
||||
out:
|
||||
kfree((void *)sgt);
|
||||
|
||||
return mtk_gem->kvaddr;
|
||||
}
|
||||
|
||||
void mtk_drm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
|
||||
{
|
||||
struct mtk_drm_gem_obj *mtk_gem = to_mtk_gem_obj(obj);
|
||||
|
||||
if (!mtk_gem->pages)
|
||||
return;
|
||||
|
||||
vunmap(vaddr);
|
||||
mtk_gem->kvaddr = 0;
|
||||
kfree((void *)mtk_gem->pages);
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ struct mtk_drm_gem_obj {
|
||||
dma_addr_t dma_addr;
|
||||
unsigned long dma_attrs;
|
||||
struct sg_table *sg;
|
||||
struct page **pages;
|
||||
};
|
||||
|
||||
#define to_mtk_gem_obj(x) container_of(x, struct mtk_drm_gem_obj, base)
|
||||
@ -52,5 +53,7 @@ int mtk_drm_gem_mmap_buf(struct drm_gem_object *obj,
|
||||
struct sg_table *mtk_gem_prime_get_sg_table(struct drm_gem_object *obj);
|
||||
struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev,
|
||||
struct dma_buf_attachment *attach, struct sg_table *sg);
|
||||
void *mtk_drm_gem_prime_vmap(struct drm_gem_object *obj);
|
||||
void mtk_drm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
|
||||
|
||||
#endif
|
||||
|
@ -1480,7 +1480,6 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
|
||||
if (IS_ERR(regmap))
|
||||
ret = PTR_ERR(regmap);
|
||||
if (ret) {
|
||||
ret = PTR_ERR(regmap);
|
||||
dev_err(dev,
|
||||
"Failed to get system configuration registers: %d\n",
|
||||
ret);
|
||||
@ -1516,6 +1515,7 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
|
||||
of_node_put(remote);
|
||||
|
||||
hdmi->ddc_adpt = of_find_i2c_adapter_by_node(i2c_np);
|
||||
of_node_put(i2c_np);
|
||||
if (!hdmi->ddc_adpt) {
|
||||
dev_err(dev, "Failed to get ddc i2c adapter by node\n");
|
||||
return -EINVAL;
|
||||
|
@ -15,28 +15,6 @@ static const struct phy_ops mtk_hdmi_phy_dev_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
|
||||
|
||||
hdmi_phy->pll_rate = rate;
|
||||
if (rate <= 74250000)
|
||||
*parent_rate = rate;
|
||||
else
|
||||
*parent_rate = rate / 2;
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
|
||||
|
||||
return hdmi_phy->pll_rate;
|
||||
}
|
||||
|
||||
void mtk_hdmi_phy_clear_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
|
||||
u32 bits)
|
||||
{
|
||||
@ -110,13 +88,11 @@ mtk_hdmi_phy_dev_get_ops(const struct mtk_hdmi_phy *hdmi_phy)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void mtk_hdmi_phy_clk_get_ops(struct mtk_hdmi_phy *hdmi_phy,
|
||||
const struct clk_ops **ops)
|
||||
static void mtk_hdmi_phy_clk_get_data(struct mtk_hdmi_phy *hdmi_phy,
|
||||
struct clk_init_data *clk_init)
|
||||
{
|
||||
if (hdmi_phy && hdmi_phy->conf && hdmi_phy->conf->hdmi_phy_clk_ops)
|
||||
*ops = hdmi_phy->conf->hdmi_phy_clk_ops;
|
||||
else
|
||||
dev_err(hdmi_phy->dev, "Failed to get clk ops of phy\n");
|
||||
clk_init->flags = hdmi_phy->conf->flags;
|
||||
clk_init->ops = hdmi_phy->conf->hdmi_phy_clk_ops;
|
||||
}
|
||||
|
||||
static int mtk_hdmi_phy_probe(struct platform_device *pdev)
|
||||
@ -129,7 +105,6 @@ static int mtk_hdmi_phy_probe(struct platform_device *pdev)
|
||||
struct clk_init_data clk_init = {
|
||||
.num_parents = 1,
|
||||
.parent_names = (const char * const *)&ref_clk_name,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
|
||||
};
|
||||
|
||||
struct phy *phy;
|
||||
@ -167,7 +142,7 @@ static int mtk_hdmi_phy_probe(struct platform_device *pdev)
|
||||
hdmi_phy->dev = dev;
|
||||
hdmi_phy->conf =
|
||||
(struct mtk_hdmi_phy_conf *)of_device_get_match_data(dev);
|
||||
mtk_hdmi_phy_clk_get_ops(hdmi_phy, &clk_init.ops);
|
||||
mtk_hdmi_phy_clk_get_data(hdmi_phy, &clk_init);
|
||||
hdmi_phy->pll_hw.init = &clk_init;
|
||||
hdmi_phy->pll = devm_clk_register(dev, &hdmi_phy->pll_hw);
|
||||
if (IS_ERR(hdmi_phy->pll)) {
|
||||
|
@ -21,6 +21,7 @@ struct mtk_hdmi_phy;
|
||||
|
||||
struct mtk_hdmi_phy_conf {
|
||||
bool tz_disabled;
|
||||
unsigned long flags;
|
||||
const struct clk_ops *hdmi_phy_clk_ops;
|
||||
void (*hdmi_phy_enable_tmds)(struct mtk_hdmi_phy *hdmi_phy);
|
||||
void (*hdmi_phy_disable_tmds)(struct mtk_hdmi_phy *hdmi_phy);
|
||||
@ -48,10 +49,6 @@ void mtk_hdmi_phy_set_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
|
||||
void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
|
||||
u32 val, u32 mask);
|
||||
struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw);
|
||||
long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate);
|
||||
unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate);
|
||||
|
||||
extern struct platform_driver mtk_hdmi_phy_driver;
|
||||
extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf;
|
||||
|
@ -79,7 +79,6 @@ static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
|
||||
usleep_range(80, 100);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
|
||||
@ -94,7 +93,6 @@ static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
|
||||
usleep_range(80, 100);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
|
||||
@ -108,6 +106,12 @@ static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
|
||||
usleep_range(80, 100);
|
||||
}
|
||||
|
||||
static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
return rate;
|
||||
}
|
||||
|
||||
static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
@ -116,13 +120,14 @@ static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
|
||||
if (rate <= 64000000)
|
||||
pos_div = 3;
|
||||
else if (rate <= 12800000)
|
||||
pos_div = 1;
|
||||
else if (rate <= 128000000)
|
||||
pos_div = 2;
|
||||
else
|
||||
pos_div = 1;
|
||||
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_PREDIV_MASK);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IC),
|
||||
RG_HTPLL_IC_MASK);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IR),
|
||||
@ -154,6 +159,39 @@ static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
|
||||
unsigned long out_rate, val;
|
||||
|
||||
val = (readl(hdmi_phy->regs + HDMI_CON6)
|
||||
& RG_HTPLL_PREDIV_MASK) >> RG_HTPLL_PREDIV;
|
||||
switch (val) {
|
||||
case 0x00:
|
||||
out_rate = parent_rate;
|
||||
break;
|
||||
case 0x01:
|
||||
out_rate = parent_rate / 2;
|
||||
break;
|
||||
default:
|
||||
out_rate = parent_rate / 4;
|
||||
break;
|
||||
}
|
||||
|
||||
val = (readl(hdmi_phy->regs + HDMI_CON6)
|
||||
& RG_HTPLL_FBKDIV_MASK) >> RG_HTPLL_FBKDIV;
|
||||
out_rate *= (val + 1) * 2;
|
||||
val = (readl(hdmi_phy->regs + HDMI_CON2)
|
||||
& RG_HDMITX_TX_POSDIV_MASK);
|
||||
out_rate >>= (val >> RG_HDMITX_TX_POSDIV);
|
||||
|
||||
if (readl(hdmi_phy->regs + HDMI_CON2) & RG_HDMITX_EN_TX_POSDIV)
|
||||
out_rate /= 5;
|
||||
|
||||
return out_rate;
|
||||
}
|
||||
|
||||
static const struct clk_ops mtk_hdmi_phy_pll_ops = {
|
||||
.prepare = mtk_hdmi_pll_prepare,
|
||||
.unprepare = mtk_hdmi_pll_unprepare,
|
||||
@ -174,7 +212,6 @@ static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy)
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
|
||||
usleep_range(80, 100);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
|
||||
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
|
||||
@ -186,7 +223,6 @@ static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
|
||||
usleep_range(80, 100);
|
||||
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
|
||||
@ -202,6 +238,7 @@ static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
|
||||
|
||||
struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf = {
|
||||
.tz_disabled = true,
|
||||
.flags = CLK_SET_RATE_GATE,
|
||||
.hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops,
|
||||
.hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds,
|
||||
.hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,
|
||||
|
@ -199,6 +199,20 @@ static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
|
||||
usleep_range(100, 150);
|
||||
}
|
||||
|
||||
static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
|
||||
|
||||
hdmi_phy->pll_rate = rate;
|
||||
if (rate <= 74250000)
|
||||
*parent_rate = rate;
|
||||
else
|
||||
*parent_rate = rate / 2;
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
@ -285,6 +299,14 @@ static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
|
||||
|
||||
return hdmi_phy->pll_rate;
|
||||
}
|
||||
|
||||
static const struct clk_ops mtk_hdmi_phy_pll_ops = {
|
||||
.prepare = mtk_hdmi_pll_prepare,
|
||||
.unprepare = mtk_hdmi_pll_unprepare,
|
||||
@ -309,6 +331,7 @@ static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
|
||||
}
|
||||
|
||||
struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf = {
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
|
||||
.hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops,
|
||||
.hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds,
|
||||
.hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,
|
||||
|
@ -175,6 +175,7 @@ static int hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
|
||||
REG_FLD_MOD(core->base, HDMI_CORE_SYS_INTR_UNMASK4, 0, 3, 3);
|
||||
hdmi_wp_clear_irqenable(core->wp, HDMI_IRQ_CORE);
|
||||
hdmi_wp_set_irqstatus(core->wp, HDMI_IRQ_CORE);
|
||||
REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0, 5, 0);
|
||||
hdmi4_core_disable(core);
|
||||
return 0;
|
||||
}
|
||||
@ -182,16 +183,24 @@ static int hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* Initialize CEC clock divider: CEC needs 2MHz clock hence
|
||||
* set the divider to 24 to get 48/24=2MHz clock
|
||||
*/
|
||||
REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0x18, 5, 0);
|
||||
|
||||
/* Clear TX FIFO */
|
||||
if (!hdmi_cec_clear_tx_fifo(adap)) {
|
||||
pr_err("cec-%s: could not clear TX FIFO\n", adap->name);
|
||||
return -EIO;
|
||||
err = -EIO;
|
||||
goto err_disable_clk;
|
||||
}
|
||||
|
||||
/* Clear RX FIFO */
|
||||
if (!hdmi_cec_clear_rx_fifo(adap)) {
|
||||
pr_err("cec-%s: could not clear RX FIFO\n", adap->name);
|
||||
return -EIO;
|
||||
err = -EIO;
|
||||
goto err_disable_clk;
|
||||
}
|
||||
|
||||
/* Clear CEC interrupts */
|
||||
@ -236,6 +245,12 @@ static int hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
|
||||
hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_1, temp);
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_disable_clk:
|
||||
REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0, 5, 0);
|
||||
hdmi4_core_disable(core);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
|
||||
@ -333,11 +348,8 @@ int hdmi4_cec_init(struct platform_device *pdev, struct hdmi_core_data *core,
|
||||
return ret;
|
||||
core->wp = wp;
|
||||
|
||||
/*
|
||||
* Initialize CEC clock divider: CEC needs 2MHz clock hence
|
||||
* set the devider to 24 to get 48/24=2MHz clock
|
||||
*/
|
||||
REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0x18, 5, 0);
|
||||
/* Disable clock initially, hdmi_cec_adap_enable() manages it */
|
||||
REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0, 5, 0);
|
||||
|
||||
ret = cec_register_adapter(core->adap, &pdev->dev);
|
||||
if (ret < 0) {
|
||||
|
@ -708,7 +708,7 @@ int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
|
||||
else
|
||||
acore.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
|
||||
/*
|
||||
* The I2S input word length is twice the lenght given in the IEC-60958
|
||||
* The I2S input word length is twice the length given in the IEC-60958
|
||||
* status word. If the word size is greater than
|
||||
* 20 bits, increment by one.
|
||||
*/
|
||||
|
@ -48,8 +48,13 @@ static enum drm_mode_status
|
||||
sun8i_dw_hdmi_mode_valid_h6(struct drm_connector *connector,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
/* This is max for HDMI 2.0b (4K@60Hz) */
|
||||
if (mode->clock > 594000)
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
if (mode->clock > 340000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
return MODE_OK;
|
||||
|
@ -227,7 +227,7 @@ static int sun8i_tcon_top_bind(struct device *dev, struct device *master,
|
||||
|
||||
err_unregister_gates:
|
||||
for (i = 0; i < CLK_NUM; i++)
|
||||
if (clk_data->hws[i])
|
||||
if (!IS_ERR_OR_NULL(clk_data->hws[i]))
|
||||
clk_hw_unregister_gate(clk_data->hws[i]);
|
||||
clk_disable_unprepare(tcon_top->bus);
|
||||
err_assert_reset:
|
||||
@ -245,7 +245,8 @@ static void sun8i_tcon_top_unbind(struct device *dev, struct device *master,
|
||||
|
||||
of_clk_del_provider(dev->of_node);
|
||||
for (i = 0; i < CLK_NUM; i++)
|
||||
clk_hw_unregister_gate(clk_data->hws[i]);
|
||||
if (clk_data->hws[i])
|
||||
clk_hw_unregister_gate(clk_data->hws[i]);
|
||||
|
||||
clk_disable_unprepare(tcon_top->bus);
|
||||
reset_control_assert(tcon_top->rst);
|
||||
|
@ -52,6 +52,7 @@ static struct drm_driver driver = {
|
||||
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
|
||||
.load = udl_driver_load,
|
||||
.unload = udl_driver_unload,
|
||||
.release = udl_driver_release,
|
||||
|
||||
/* gem hooks */
|
||||
.gem_free_object_unlocked = udl_gem_free_object,
|
||||
|
@ -104,6 +104,7 @@ void udl_urb_completion(struct urb *urb);
|
||||
|
||||
int udl_driver_load(struct drm_device *dev, unsigned long flags);
|
||||
void udl_driver_unload(struct drm_device *dev);
|
||||
void udl_driver_release(struct drm_device *dev);
|
||||
|
||||
int udl_fbdev_init(struct drm_device *dev);
|
||||
void udl_fbdev_cleanup(struct drm_device *dev);
|
||||
|
@ -379,6 +379,12 @@ void udl_driver_unload(struct drm_device *dev)
|
||||
udl_free_urb_list(dev);
|
||||
|
||||
udl_fbdev_cleanup(dev);
|
||||
udl_modeset_cleanup(dev);
|
||||
kfree(udl);
|
||||
}
|
||||
|
||||
void udl_driver_release(struct drm_device *dev)
|
||||
{
|
||||
udl_modeset_cleanup(dev);
|
||||
drm_dev_fini(dev);
|
||||
kfree(dev);
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ static inline void synchronize_syncpt_base(struct host1x_job *job)
|
||||
|
||||
static void host1x_channel_set_streamid(struct host1x_channel *channel)
|
||||
{
|
||||
#if HOST1X_HW >= 6
|
||||
#if IS_ENABLED(CONFIG_IOMMU_API) && HOST1X_HW >= 6
|
||||
struct iommu_fwspec *spec = dev_iommu_fwspec_get(channel->dev->parent);
|
||||
u32 sid = spec ? spec->ids[0] & 0xffff : 0x7f;
|
||||
|
||||
|
@ -418,6 +418,8 @@ struct drm_crtc_helper_funcs {
|
||||
* Drivers can use the @old_crtc_state input parameter if the operations
|
||||
* needed to enable the CRTC don't depend solely on the new state but
|
||||
* also on the transition between the old state and the new state.
|
||||
*
|
||||
* This function is optional.
|
||||
*/
|
||||
void (*atomic_enable)(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *old_crtc_state);
|
||||
@ -441,6 +443,8 @@ struct drm_crtc_helper_funcs {
|
||||
* parameter @old_crtc_state which could be used to access the old
|
||||
* state. Atomic drivers should consider to use this one instead
|
||||
* of @disable.
|
||||
*
|
||||
* This function is optional.
|
||||
*/
|
||||
void (*atomic_disable)(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *old_crtc_state);
|
||||
|
Loading…
Reference in New Issue
Block a user