Commit 961b708e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'drm-fixes-for-v4.9-rc6' of git://people.freedesktop.org/~airlied/linux

Pull drm fixes fr9om Dave Airlie:
 "Fixes for amdgpu, and a bunch of arm drivers.

  There seems to be an uptick in the ARM drivers sending things for
  fixes which is good, so I've decided to dequeue a bit early, more
  stuff may arrive before the weekend.

  This contains mediatek, arcpgu, sunxi, fsl-dcu display controller
  fixes along with 3 amdgpu fixes, one for a fencing issue with
  secondary GPUs"

* tag 'drm-fixes-for-v4.9-rc6' of git://people.freedesktop.org/~airlied/linux:
  drm/amdgpu:fix vpost_needed routine
  drm/amdgpu/powerplay: drop a redundant NULL check
  drm/amdgpu: Attach exclusive fence to prime exported bo's. (v5)
  drm/arcpgu: Accommodate adv7511 switch to DRM bridge
  drm/fsl-dcu: disable planes before disabling CRTC
  drm/fsl-dcu: update all registers on flush
  drm/fsl-dcu: do not update when modifying irq registers
  drm/sun4i: Propagate error to the caller
  drm/sun4i: Fix error handling
  drm/mediatek: modify the factor to make the pll_rate set in the 1G-2G range
  drm/mediatek: enhance the HDMI driving current
  drm/mediatek: do mtk_hdmi_send_infoframe after HDMI clock enable
  drm/mediatek: clear IRQ status before enable OVL interrupt
  drm/mediatek: set vblank_disable_allowed to true
  drm/mediatek: fix a typo of OD_CFG to OD_RELAYMODE
  drm/sun4i: rgb: Remove the bridge enable/disable functions
  drm/sun4i: rgb: Enable panel after controller
parents 5fd0f1ca 29ed1973
...@@ -459,6 +459,7 @@ struct amdgpu_bo { ...@@ -459,6 +459,7 @@ struct amdgpu_bo {
u64 metadata_flags; u64 metadata_flags;
void *metadata; void *metadata;
u32 metadata_size; u32 metadata_size;
unsigned prime_shared_count;
/* list of all virtual address to which this bo /* list of all virtual address to which this bo
* is associated to * is associated to
*/ */
......
...@@ -132,7 +132,7 @@ static int amdgpu_bo_list_set(struct amdgpu_device *adev, ...@@ -132,7 +132,7 @@ static int amdgpu_bo_list_set(struct amdgpu_device *adev,
entry->priority = min(info[i].bo_priority, entry->priority = min(info[i].bo_priority,
AMDGPU_BO_LIST_MAX_PRIORITY); AMDGPU_BO_LIST_MAX_PRIORITY);
entry->tv.bo = &entry->robj->tbo; entry->tv.bo = &entry->robj->tbo;
entry->tv.shared = true; entry->tv.shared = !entry->robj->prime_shared_count;
if (entry->robj->prefered_domains == AMDGPU_GEM_DOMAIN_GDS) if (entry->robj->prefered_domains == AMDGPU_GEM_DOMAIN_GDS)
gds_obj = entry->robj; gds_obj = entry->robj;
......
...@@ -658,12 +658,10 @@ static bool amdgpu_vpost_needed(struct amdgpu_device *adev) ...@@ -658,12 +658,10 @@ static bool amdgpu_vpost_needed(struct amdgpu_device *adev)
return false; return false;
if (amdgpu_passthrough(adev)) { if (amdgpu_passthrough(adev)) {
/* for FIJI: In whole GPU pass-through virtualization case /* for FIJI: In whole GPU pass-through virtualization case, after VM reboot
* old smc fw won't clear some registers (e.g. MEM_SIZE, BIOS_SCRATCH) * some old smc fw still need driver do vPost otherwise gpu hang, while
* so amdgpu_card_posted return false and driver will incorrectly skip vPost. * those smc fw version above 22.15 doesn't have this flaw, so we force
* but if we force vPost do in pass-through case, the driver reload will hang. * vpost executed for smc version below 22.15
* whether doing vPost depends on amdgpu_card_posted if smc version is above
* 00160e00 for FIJI.
*/ */
if (adev->asic_type == CHIP_FIJI) { if (adev->asic_type == CHIP_FIJI) {
int err; int err;
...@@ -674,22 +672,11 @@ static bool amdgpu_vpost_needed(struct amdgpu_device *adev) ...@@ -674,22 +672,11 @@ static bool amdgpu_vpost_needed(struct amdgpu_device *adev)
return true; return true;
fw_ver = *((uint32_t *)adev->pm.fw->data + 69); fw_ver = *((uint32_t *)adev->pm.fw->data + 69);
if (fw_ver >= 0x00160e00) if (fw_ver < 0x00160e00)
return !amdgpu_card_posted(adev); return true;
} }
} else {
/* in bare-metal case, amdgpu_card_posted return false
* after system reboot/boot, and return true if driver
* reloaded.
* we shouldn't do vPost after driver reload otherwise GPU
* could hang.
*/
if (amdgpu_card_posted(adev))
return false;
} }
return !amdgpu_card_posted(adev);
/* we assume vPost is neede for all other cases */
return true;
} }
/** /**
......
...@@ -74,20 +74,36 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev, ...@@ -74,20 +74,36 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(ret);
bo->prime_shared_count = 1;
return &bo->gem_base; return &bo->gem_base;
} }
int amdgpu_gem_prime_pin(struct drm_gem_object *obj) int amdgpu_gem_prime_pin(struct drm_gem_object *obj)
{ {
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
int ret = 0; long ret = 0;
ret = amdgpu_bo_reserve(bo, false); ret = amdgpu_bo_reserve(bo, false);
if (unlikely(ret != 0)) if (unlikely(ret != 0))
return ret; return ret;
/*
* Wait for all shared fences to complete before we switch to future
* use of exclusive fence on this prime shared bo.
*/
ret = reservation_object_wait_timeout_rcu(bo->tbo.resv, true, false,
MAX_SCHEDULE_TIMEOUT);
if (unlikely(ret < 0)) {
DRM_DEBUG_PRIME("Fence wait failed: %li\n", ret);
amdgpu_bo_unreserve(bo);
return ret;
}
/* pin buffer into GTT */ /* pin buffer into GTT */
ret = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT, NULL); ret = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT, NULL);
if (likely(ret == 0))
bo->prime_shared_count++;
amdgpu_bo_unreserve(bo); amdgpu_bo_unreserve(bo);
return ret; return ret;
} }
...@@ -102,6 +118,8 @@ void amdgpu_gem_prime_unpin(struct drm_gem_object *obj) ...@@ -102,6 +118,8 @@ void amdgpu_gem_prime_unpin(struct drm_gem_object *obj)
return; return;
amdgpu_bo_unpin(bo); amdgpu_bo_unpin(bo);
if (bo->prime_shared_count)
bo->prime_shared_count--;
amdgpu_bo_unreserve(bo); amdgpu_bo_unreserve(bo);
} }
......
...@@ -1469,8 +1469,6 @@ static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr) ...@@ -1469,8 +1469,6 @@ static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr)
table_info->vddgfx_lookup_table, vv_id, &sclk)) { table_info->vddgfx_lookup_table, vv_id, &sclk)) {
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_ClockStretcher)) { PHM_PlatformCaps_ClockStretcher)) {
if (table_info == NULL)
return -EINVAL;
sclk_table = table_info->vdd_dep_on_sclk; sclk_table = table_info->vdd_dep_on_sclk;
for (j = 1; j < sclk_table->count; j++) { for (j = 1; j < sclk_table->count; j++) {
......
...@@ -14,170 +14,45 @@ ...@@ -14,170 +14,45 @@
* *
*/ */
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc.h>
#include <drm/drm_encoder_slave.h> #include <drm/drm_encoder_slave.h>
#include <drm/drm_atomic_helper.h>
#include "arcpgu.h" #include "arcpgu.h"
struct arcpgu_drm_connector {
struct drm_connector connector;
struct drm_encoder_slave *encoder_slave;
};
static int arcpgu_drm_connector_get_modes(struct drm_connector *connector)
{
const struct drm_encoder_slave_funcs *sfuncs;
struct drm_encoder_slave *slave;
struct arcpgu_drm_connector *con =
container_of(connector, struct arcpgu_drm_connector, connector);
slave = con->encoder_slave;
if (slave == NULL) {
dev_err(connector->dev->dev,
"connector_get_modes: cannot find slave encoder for connector\n");
return 0;
}
sfuncs = slave->slave_funcs;
if (sfuncs->get_modes == NULL)
return 0;
return sfuncs->get_modes(&slave->base, connector);
}
static enum drm_connector_status
arcpgu_drm_connector_detect(struct drm_connector *connector, bool force)
{
enum drm_connector_status status = connector_status_unknown;
const struct drm_encoder_slave_funcs *sfuncs;
struct drm_encoder_slave *slave;
struct arcpgu_drm_connector *con =
container_of(connector, struct arcpgu_drm_connector, connector);
slave = con->encoder_slave;
if (slave == NULL) {
dev_err(connector->dev->dev,
"connector_detect: cannot find slave encoder for connector\n");
return status;
}
sfuncs = slave->slave_funcs;
if (sfuncs && sfuncs->detect)
return sfuncs->detect(&slave->base, connector);
dev_err(connector->dev->dev, "connector_detect: could not detect slave funcs\n");
return status;
}
static void arcpgu_drm_connector_destroy(struct drm_connector *connector)
{
drm_connector_unregister(connector);
drm_connector_cleanup(connector);
}
static const struct drm_connector_helper_funcs
arcpgu_drm_connector_helper_funcs = {
.get_modes = arcpgu_drm_connector_get_modes,
};
static const struct drm_connector_funcs arcpgu_drm_connector_funcs = {
.dpms = drm_helper_connector_dpms,
.reset = drm_atomic_helper_connector_reset,
.detect = arcpgu_drm_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = arcpgu_drm_connector_destroy,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
static struct drm_encoder_helper_funcs arcpgu_drm_encoder_helper_funcs = {
.dpms = drm_i2c_encoder_dpms,
.mode_fixup = drm_i2c_encoder_mode_fixup,
.mode_set = drm_i2c_encoder_mode_set,
.prepare = drm_i2c_encoder_prepare,
.commit = drm_i2c_encoder_commit,
.detect = drm_i2c_encoder_detect,
};
static struct drm_encoder_funcs arcpgu_drm_encoder_funcs = { static struct drm_encoder_funcs arcpgu_drm_encoder_funcs = {
.destroy = drm_encoder_cleanup, .destroy = drm_encoder_cleanup,
}; };
int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np) int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np)
{ {
struct arcpgu_drm_connector *arcpgu_connector; struct drm_encoder *encoder;
struct drm_i2c_encoder_driver *driver; struct drm_bridge *bridge;
struct drm_encoder_slave *encoder;
struct drm_connector *connector; int ret = 0;
struct i2c_client *i2c_slave;
int ret;
encoder = devm_kzalloc(drm->dev, sizeof(*encoder), GFP_KERNEL); encoder = devm_kzalloc(drm->dev, sizeof(*encoder), GFP_KERNEL);
if (encoder == NULL) if (encoder == NULL)
return -ENOMEM; return -ENOMEM;
i2c_slave = of_find_i2c_device_by_node(np); /* Locate drm bridge from the hdmi encoder DT node */
if (!i2c_slave || !i2c_get_clientdata(i2c_slave)) { bridge = of_drm_find_bridge(np);
dev_err(drm->dev, "failed to find i2c slave encoder\n"); if (!bridge)
return -EPROBE_DEFER;
}
if (i2c_slave->dev.driver == NULL) {
dev_err(drm->dev, "failed to find i2c slave driver\n");
return -EPROBE_DEFER; return -EPROBE_DEFER;
}
driver = encoder->possible_crtcs = 1;
to_drm_i2c_encoder_driver(to_i2c_driver(i2c_slave->dev.driver)); encoder->possible_clones = 0;
ret = driver->encoder_init(i2c_slave, drm, encoder); ret = drm_encoder_init(drm, encoder, &arcpgu_drm_encoder_funcs,
if (ret) {
dev_err(drm->dev, "failed to initialize i2c encoder slave\n");
return ret;
}
encoder->base.possible_crtcs = 1;
encoder->base.possible_clones = 0;
ret = drm_encoder_init(drm, &encoder->base, &arcpgu_drm_encoder_funcs,
DRM_MODE_ENCODER_TMDS, NULL); DRM_MODE_ENCODER_TMDS, NULL);
if (ret) if (ret)
return ret; return ret;
drm_encoder_helper_add(&encoder->base, /* Link drm_bridge to encoder */
&arcpgu_drm_encoder_helper_funcs); bridge->encoder = encoder;
encoder->bridge = bridge;
arcpgu_connector = devm_kzalloc(drm->dev, sizeof(*arcpgu_connector),
GFP_KERNEL);
if (!arcpgu_connector) {
ret = -ENOMEM;
goto error_encoder_cleanup;
}
connector = &arcpgu_connector->connector;
drm_connector_helper_add(connector, &arcpgu_drm_connector_helper_funcs);
ret = drm_connector_init(drm, connector, &arcpgu_drm_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA);
if (ret < 0) {
dev_err(drm->dev, "failed to initialize drm connector\n");
goto error_encoder_cleanup;
}
ret = drm_mode_connector_attach_encoder(connector, &encoder->base); ret = drm_bridge_attach(drm, bridge);
if (ret < 0) { if (ret)
dev_err(drm->dev, "could not attach connector to encoder\n"); drm_encoder_cleanup(encoder);
drm_connector_unregister(connector);
goto error_connector_cleanup;
}
arcpgu_connector->encoder_slave = encoder;
return 0;
error_connector_cleanup:
drm_connector_cleanup(connector);
error_encoder_cleanup:
drm_encoder_cleanup(&encoder->base);
return ret; return ret;
} }
...@@ -25,8 +25,13 @@ ...@@ -25,8 +25,13 @@
static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc, static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state) struct drm_crtc_state *old_crtc_state)
{ {
struct drm_device *dev = crtc->dev;
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
struct drm_pending_vblank_event *event = crtc->state->event; struct drm_pending_vblank_event *event = crtc->state->event;
regmap_write(fsl_dev->regmap,
DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
if (event) { if (event) {
crtc->state->event = NULL; crtc->state->event = NULL;
...@@ -39,11 +44,15 @@ static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc, ...@@ -39,11 +44,15 @@ static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc,
} }
} }
static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc) static void fsl_dcu_drm_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
/* always disable planes on the CRTC */
drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, true);
drm_crtc_vblank_off(crtc); drm_crtc_vblank_off(crtc);
regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE, regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
...@@ -122,8 +131,8 @@ static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) ...@@ -122,8 +131,8 @@ static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
} }
static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = { static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = {
.atomic_disable = fsl_dcu_drm_crtc_atomic_disable,
.atomic_flush = fsl_dcu_drm_crtc_atomic_flush, .atomic_flush = fsl_dcu_drm_crtc_atomic_flush,
.disable = fsl_dcu_drm_disable_crtc,
.enable = fsl_dcu_drm_crtc_enable, .enable = fsl_dcu_drm_crtc_enable,
.mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb, .mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb,
}; };
......
...@@ -59,8 +59,6 @@ static int fsl_dcu_drm_irq_init(struct drm_device *dev) ...@@ -59,8 +59,6 @@ static int fsl_dcu_drm_irq_init(struct drm_device *dev)
regmap_write(fsl_dev->regmap, DCU_INT_STATUS, 0); regmap_write(fsl_dev->regmap, DCU_INT_STATUS, 0);
regmap_write(fsl_dev->regmap, DCU_INT_MASK, ~0); regmap_write(fsl_dev->regmap, DCU_INT_MASK, ~0);
regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
DCU_UPDATE_MODE_READREG);
return ret; return ret;
} }
...@@ -139,8 +137,6 @@ static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg) ...@@ -139,8 +137,6 @@ static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
drm_handle_vblank(dev, 0); drm_handle_vblank(dev, 0);
regmap_write(fsl_dev->regmap, DCU_INT_STATUS, int_status); regmap_write(fsl_dev->regmap, DCU_INT_STATUS, int_status);
regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
DCU_UPDATE_MODE_READREG);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -160,11 +160,6 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane, ...@@ -160,11 +160,6 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
DCU_LAYER_POST_SKIP(0) | DCU_LAYER_POST_SKIP(0) |
DCU_LAYER_PRE_SKIP(0)); DCU_LAYER_PRE_SKIP(0));
} }
regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
DCU_MODE_DCU_MODE_MASK,
DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
regmap_write(fsl_dev->regmap,
DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
return; return;
} }
......
...@@ -80,6 +80,7 @@ static void mtk_ovl_enable_vblank(struct mtk_ddp_comp *comp, ...@@ -80,6 +80,7 @@ static void mtk_ovl_enable_vblank(struct mtk_ddp_comp *comp,
ddp_comp); ddp_comp);
priv->crtc = crtc; priv->crtc = crtc;
writel(0x0, comp->regs + DISP_REG_OVL_INTSTA);
writel_relaxed(OVL_FME_CPL_INT, comp->regs + DISP_REG_OVL_INTEN); writel_relaxed(OVL_FME_CPL_INT, comp->regs + DISP_REG_OVL_INTEN);
} }
......
...@@ -432,11 +432,16 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi, ...@@ -432,11 +432,16 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
unsigned long pll_rate; unsigned long pll_rate;
unsigned int factor; unsigned int factor;
/* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */
pix_rate = 1000UL * mode->clock; pix_rate = 1000UL * mode->clock;
if (mode->clock <= 74000) if (mode->clock <= 27000)
factor = 16 * 3;
else if (mode->clock <= 84000)
factor = 8 * 3; factor = 8 * 3;
else else if (mode->clock <= 167000)
factor = 4 * 3; factor = 4 * 3;
else
factor = 2 * 3;
pll_rate = pix_rate * factor; pll_rate = pix_rate * factor;
dev_dbg(dpi->dev, "Want PLL %lu Hz, pixel clock %lu Hz\n", dev_dbg(dpi->dev, "Want PLL %lu Hz, pixel clock %lu Hz\n",
......
...@@ -123,7 +123,7 @@ static void mtk_od_config(struct mtk_ddp_comp *comp, unsigned int w, ...@@ -123,7 +123,7 @@ static void mtk_od_config(struct mtk_ddp_comp *comp, unsigned int w,
unsigned int bpc) unsigned int bpc)
{ {
writel(w << 16 | h, comp->regs + DISP_OD_SIZE); writel(w << 16 | h, comp->regs + DISP_OD_SIZE);
writel(OD_RELAYMODE, comp->regs + OD_RELAYMODE); writel(OD_RELAYMODE, comp->regs + OD_CFG);
mtk_dither_set(comp, bpc, DISP_OD_CFG); mtk_dither_set(comp, bpc, DISP_OD_CFG);
} }
......
...@@ -217,6 +217,7 @@ static int mtk_drm_kms_init(struct drm_device *drm) ...@@ -217,6 +217,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
if (ret < 0) if (ret < 0)
goto err_component_unbind; goto err_component_unbind;
drm->vblank_disable_allowed = true;
drm_kms_helper_poll_init(drm); drm_kms_helper_poll_init(drm);
drm_mode_config_reset(drm); drm_mode_config_reset(drm);
......
...@@ -1133,12 +1133,6 @@ static int mtk_hdmi_output_set_display_mode(struct mtk_hdmi *hdmi, ...@@ -1133,12 +1133,6 @@ static int mtk_hdmi_output_set_display_mode(struct mtk_hdmi *hdmi,
phy_power_on(hdmi->phy); phy_power_on(hdmi->phy);
mtk_hdmi_aud_output_config(hdmi, mode); mtk_hdmi_aud_output_config(hdmi, mode);
mtk_hdmi_setup_audio_infoframe(hdmi);
mtk_hdmi_setup_avi_infoframe(hdmi, mode);
mtk_hdmi_setup_spd_infoframe(hdmi, "mediatek", "On-chip HDMI");
if (mode->flags & DRM_MODE_FLAG_3D_MASK)
mtk_hdmi_setup_vendor_specific_infoframe(hdmi, mode);
mtk_hdmi_hw_vid_black(hdmi, false); mtk_hdmi_hw_vid_black(hdmi, false);
mtk_hdmi_hw_aud_unmute(hdmi); mtk_hdmi_hw_aud_unmute(hdmi);
mtk_hdmi_hw_send_av_unmute(hdmi); mtk_hdmi_hw_send_av_unmute(hdmi);
...@@ -1401,6 +1395,16 @@ static void mtk_hdmi_bridge_pre_enable(struct drm_bridge *bridge) ...@@ -1401,6 +1395,16 @@ static void mtk_hdmi_bridge_pre_enable(struct drm_bridge *bridge)
hdmi->powered = true; hdmi->powered = true;
} }
static void mtk_hdmi_send_infoframe(struct mtk_hdmi *hdmi,
struct drm_display_mode *mode)
{
mtk_hdmi_setup_audio_infoframe(hdmi);
mtk_hdmi_setup_avi_infoframe(hdmi, mode);
mtk_hdmi_setup_spd_infoframe(hdmi, "mediatek", "On-chip HDMI");
if (mode->flags & DRM_MODE_FLAG_3D_MASK)
mtk_hdmi_setup_vendor_specific_infoframe(hdmi, mode);
}
static void mtk_hdmi_bridge_enable(struct drm_bridge *bridge) static void mtk_hdmi_bridge_enable(struct drm_bridge *bridge)
{ {
struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
...@@ -1409,6 +1413,7 @@ static void mtk_hdmi_bridge_enable(struct drm_bridge *bridge) ...@@ -1409,6 +1413,7 @@ static void mtk_hdmi_bridge_enable(struct drm_bridge *bridge)
clk_prepare_enable(hdmi->clk[MTK_HDMI_CLK_HDMI_PLL]); clk_prepare_enable(hdmi->clk[MTK_HDMI_CLK_HDMI_PLL]);
clk_prepare_enable(hdmi->clk[MTK_HDMI_CLK_HDMI_PIXEL]); clk_prepare_enable(hdmi->clk[MTK_HDMI_CLK_HDMI_PIXEL]);
phy_power_on(hdmi->phy); phy_power_on(hdmi->phy);
mtk_hdmi_send_infoframe(hdmi, &hdmi->mode);
hdmi->enabled = true; hdmi->enabled = true;
} }
......
...@@ -265,6 +265,9 @@ static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -265,6 +265,9 @@ static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw); struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
unsigned int pre_div; unsigned int pre_div;
unsigned int div; unsigned int div;
unsigned int pre_ibias;
unsigned int hdmi_ibias;
unsigned int imp_en;
dev_dbg(hdmi_phy->dev, "%s: %lu Hz, parent: %lu Hz\n", __func__, dev_dbg(hdmi_phy->dev, "%s: %lu Hz, parent: %lu Hz\n", __func__,
rate, parent_rate); rate, parent_rate);
...@@ -298,18 +301,31 @@ static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -298,18 +301,31 @@ static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
(0x1 << PLL_BR_SHIFT), (0x1 << PLL_BR_SHIFT),
RG_HDMITX_PLL_BP | RG_HDMITX_PLL_BC | RG_HDMITX_PLL_BP | RG_HDMITX_PLL_BC |
RG_HDMITX_PLL_BR); RG_HDMITX_PLL_BR);
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3, RG_HDMITX_PRD_IMP_EN); if (rate < 165000000) {
mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3,
RG_HDMITX_PRD_IMP_EN);
pre_ibias = 0x3;
imp_en = 0x0;
hdmi_ibias = hdmi_phy->ibias;
} else {
mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON3,
RG_HDMITX_PRD_IMP_EN);
pre_ibias = 0x6;
imp_en = 0xf;
hdmi_ibias = hdmi_phy->ibias_up;
}
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON4, mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON4,
(0x3 << PRD_IBIAS_CLK_SHIFT) | (pre_ibias << PRD_IBIAS_CLK_SHIFT) |
(0x3 << PRD_IBIAS_D2_SHIFT) | (pre_ibias << PRD_IBIAS_D2_SHIFT) |
(0x3 << PRD_IBIAS_D1_SHIFT) | (pre_ibias << PRD_IBIAS_D1_SHIFT) |
(0x3 << PRD_IBIAS_D0_SHIFT), (pre_ibias << PRD_IBIAS_D0_SHIFT),
RG_HDMITX_PRD_IBIAS_CLK | RG_HDMITX_PRD_IBIAS_CLK |
RG_HDMITX_PRD_IBIAS_D2 | RG_HDMITX_PRD_IBIAS_D2 |
RG_HDMITX_PRD_IBIAS_D1 | RG_HDMITX_PRD_IBIAS_D1 |
RG_HDMITX_PRD_IBIAS_D0); RG_HDMITX_PRD_IBIAS_D0);
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON3, mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON3,
(0x0 << DRV_IMP_EN_SHIFT), RG_HDMITX_DRV_IMP_EN); (imp_en << DRV_IMP_EN_SHIFT),
RG_HDMITX_DRV_IMP_EN);
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6,
(hdmi_phy->drv_imp_clk << DRV_IMP_CLK_SHIFT) | (hdmi_phy->drv_imp_clk << DRV_IMP_CLK_SHIFT) |
(hdmi_phy->drv_imp_d2 << DRV_IMP_D2_SHIFT) | (hdmi_phy->drv_imp_d2 << DRV_IMP_D2_SHIFT) |
...@@ -318,12 +334,14 @@ static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -318,12 +334,14 @@ static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
RG_HDMITX_DRV_IMP_CLK | RG_HDMITX_DRV_IMP_D2 | RG_HDMITX_DRV_IMP_CLK | RG_HDMITX_DRV_IMP_D2 |
RG_HDMITX_DRV_IMP_D1 | RG_HDMITX_DRV_IMP_D0); RG_HDMITX_DRV_IMP_D1 | RG_HDMITX_DRV_IMP_D0);
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON5, mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON5,
(hdmi_phy->ibias << DRV_IBIAS_CLK_SHIFT) | (hdmi_ibias << DRV_IBIAS_CLK_SHIFT) |
(hdmi_phy->ibias << DRV_IBIAS_D2_SHIFT) | (hdmi_ibias << DRV_IBIAS_D2_SHIFT) |
(hdmi_phy->ibias << DRV_IBIAS_D1_SHIFT) | (hdmi_ibias << DRV_IBIAS_D1_SHIFT) |
(hdmi_phy->ibias << DRV_IBIAS_D0_SHIFT), (hdmi_ibias << DRV_IBIAS_D0_SHIFT),
RG_HDMITX_DRV_IBIAS_CLK | RG_HDMITX_DRV_IBIAS_D2 | RG_HDMITX_DRV_IBIAS_CLK |
RG_HDMITX_DRV_IBIAS_D1 | RG_HDMITX_DRV_IBIAS_D0); RG_HDMITX_DRV_IBIAS_D2 |
RG_HDMITX_DRV_IBIAS_D1 |
RG_HDMITX_DRV_IBIAS_D0);
return 0; return 0;
} }
......
...@@ -142,9 +142,9 @@ static int sun4i_drv_bind(struct device *dev) ...@@ -142,9 +142,9 @@ static int sun4i_drv_bind(struct device *dev)
/* Create our layers */ /* Create our layers */
drv->layers = sun4i_layers_init(drm); drv->layers = sun4i_layers_init(drm);
if (!drv->layers) { if (IS_ERR(drv->layers)) {
dev_err(drm->dev, "Couldn't create the planes\n"); dev_err(drm->dev, "Couldn't create the planes\n");
ret = -EINVAL; ret = PTR_ERR(drv->layers);
goto free_drm; goto free_drm;
} }
......
...@@ -152,15 +152,13 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder) ...@@ -152,15 +152,13 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder)
DRM_DEBUG_DRIVER("Enabling RGB output\n"); DRM_DEBUG_DRIVER("Enabling RGB output\n");
if (!IS_ERR(tcon->panel)) { if (!IS_ERR(tcon->panel))
drm_panel_prepare(tcon->panel); drm_panel_prepare(tcon->panel);
drm_panel_enable(tcon->panel);
}
/* encoder->bridge can be NULL; drm_bridge_enable checks for it */
drm_bridge_enable(encoder->bridge);
sun4i_tcon_channel_enable(tcon, 0); sun4i_tcon_channel_enable(tcon, 0);
if (!IS_ERR(tcon->panel))
drm_panel_enable(tcon->panel);
} }
static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder) static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
...@@ -171,15 +169,13 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder) ...@@ -171,15 +169,13 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
DRM_DEBUG_DRIVER("Disabling RGB output\n"); DRM_DEBUG_DRIVER("Disabling RGB output\n");
sun4i_tcon_channel_disable(tcon, 0); if (!IS_ERR(tcon->panel))
drm_panel_disable(tcon->panel);
/* encoder->bridge can be NULL; drm_bridge_disable checks for it */ sun4i_tcon_channel_disable(tcon, 0);
drm_bridge_disable(encoder->bridge);
if (!IS_ERR(tcon->panel)) { if (!IS_ERR(tcon->panel))
drm_panel_disable(tcon->panel);
drm_panel_unprepare(tcon->panel); drm_panel_unprepare(tcon->panel);
}
} }
static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder, static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment