forked from Minki/linux
fixes for amdgpu, and a bunch of arm drivers.
-----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJYLPBxAAoJEAx081l5xIa+qfIQAJCK90sXfXwGdvYcQLkYQgho WvgRAL04U15tI29oyy96gSwLWk+1S6kLmXOKMmzlNCxdAaVMa3GhXOq/Zixxi2aR a2blw05r2Pp/CC/TDf9xNlgmZIVWWjlHSOzKyi4KgelZWz1yG02LsiO6nQZQlm2z IF8b83lLAQGey4EOEGGpQBkHa7oxfglWwq8XjjwuqREc8os0FFq/5WivBKu+QOA9 TwUv7FNjqeV5NzV9JNp94tFKYE3QldNemT0hrmYFud4R4JADs+QEwZ9yokRa6DF8 RXU18xxRzmpZMGL2aXE/KqivEHY7FLsVg2m+KAZJZtbKo8Et2Bz5etEjvH4v0SXn 1FJRSplXIcggleOPlurhT2XvIr0vqgIdcdizsXdN0+f2tKQljTDRgES825MTFQWm mY1AEVtcDI6GdJcSCORUCr5K1pyBlaMCqYs8jgIznBoX8VrxMx6VpA0u9r7/rX60 WRcUMXkqr+cR/3NEcu2YvN3c8M/TX1gmEek8URWm2EEE8SmwxnMudQLYNgeqBFSn i1LeNOtmFcG6MCwYQCbsNEz7iYJOjwgsZLoJh6WMNYCuUg9l7syVxXgg5l5q3DFc UnvDLPIxnPe+BtMXAodlueEmaPK0niytqIc8RGWx9RWu5TsN9S+I6BmS9PjCd43X GzMfpPGbY/57BMdddQh7 =TZCv -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
961b708e95
@ -459,6 +459,7 @@ struct amdgpu_bo {
|
||||
u64 metadata_flags;
|
||||
void *metadata;
|
||||
u32 metadata_size;
|
||||
unsigned prime_shared_count;
|
||||
/* list of all virtual address to which this bo
|
||||
* is associated to
|
||||
*/
|
||||
|
@ -132,7 +132,7 @@ static int amdgpu_bo_list_set(struct amdgpu_device *adev,
|
||||
entry->priority = min(info[i].bo_priority,
|
||||
AMDGPU_BO_LIST_MAX_PRIORITY);
|
||||
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)
|
||||
gds_obj = entry->robj;
|
||||
|
@ -658,12 +658,10 @@ static bool amdgpu_vpost_needed(struct amdgpu_device *adev)
|
||||
return false;
|
||||
|
||||
if (amdgpu_passthrough(adev)) {
|
||||
/* for FIJI: In whole GPU pass-through virtualization case
|
||||
* old smc fw won't clear some registers (e.g. MEM_SIZE, BIOS_SCRATCH)
|
||||
* so amdgpu_card_posted return false and driver will incorrectly skip vPost.
|
||||
* but if we force vPost do in pass-through case, the driver reload will hang.
|
||||
* whether doing vPost depends on amdgpu_card_posted if smc version is above
|
||||
* 00160e00 for FIJI.
|
||||
/* for FIJI: In whole GPU pass-through virtualization case, after VM reboot
|
||||
* some old smc fw still need driver do vPost otherwise gpu hang, while
|
||||
* those smc fw version above 22.15 doesn't have this flaw, so we force
|
||||
* vpost executed for smc version below 22.15
|
||||
*/
|
||||
if (adev->asic_type == CHIP_FIJI) {
|
||||
int err;
|
||||
@ -674,22 +672,11 @@ static bool amdgpu_vpost_needed(struct amdgpu_device *adev)
|
||||
return true;
|
||||
|
||||
fw_ver = *((uint32_t *)adev->pm.fw->data + 69);
|
||||
if (fw_ver >= 0x00160e00)
|
||||
return !amdgpu_card_posted(adev);
|
||||
if (fw_ver < 0x00160e00)
|
||||
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;
|
||||
}
|
||||
|
||||
/* we assume vPost is neede for all other cases */
|
||||
return true;
|
||||
return !amdgpu_card_posted(adev);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,20 +74,36 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
bo->prime_shared_count = 1;
|
||||
return &bo->gem_base;
|
||||
}
|
||||
|
||||
int amdgpu_gem_prime_pin(struct drm_gem_object *obj)
|
||||
{
|
||||
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
|
||||
int ret = 0;
|
||||
long ret = 0;
|
||||
|
||||
ret = amdgpu_bo_reserve(bo, false);
|
||||
if (unlikely(ret != 0))
|
||||
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 */
|
||||
ret = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT, NULL);
|
||||
if (likely(ret == 0))
|
||||
bo->prime_shared_count++;
|
||||
|
||||
amdgpu_bo_unreserve(bo);
|
||||
return ret;
|
||||
}
|
||||
@ -102,6 +118,8 @@ void amdgpu_gem_prime_unpin(struct drm_gem_object *obj)
|
||||
return;
|
||||
|
||||
amdgpu_bo_unpin(bo);
|
||||
if (bo->prime_shared_count)
|
||||
bo->prime_shared_count--;
|
||||
amdgpu_bo_unreserve(bo);
|
||||
}
|
||||
|
||||
|
@ -1469,8 +1469,6 @@ static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr)
|
||||
table_info->vddgfx_lookup_table, vv_id, &sclk)) {
|
||||
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
|
||||
PHM_PlatformCaps_ClockStretcher)) {
|
||||
if (table_info == NULL)
|
||||
return -EINVAL;
|
||||
sclk_table = table_info->vdd_dep_on_sclk;
|
||||
|
||||
for (j = 1; j < sclk_table->count; j++) {
|
||||
|
@ -14,170 +14,45 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_encoder_slave.h>
|
||||
#include <drm/drm_atomic_helper.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 = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np)
|
||||
{
|
||||
struct arcpgu_drm_connector *arcpgu_connector;
|
||||
struct drm_i2c_encoder_driver *driver;
|
||||
struct drm_encoder_slave *encoder;
|
||||
struct drm_connector *connector;
|
||||
struct i2c_client *i2c_slave;
|
||||
int ret;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_bridge *bridge;
|
||||
|
||||
int ret = 0;
|
||||
|
||||
encoder = devm_kzalloc(drm->dev, sizeof(*encoder), GFP_KERNEL);
|
||||
if (encoder == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_slave = of_find_i2c_device_by_node(np);
|
||||
if (!i2c_slave || !i2c_get_clientdata(i2c_slave)) {
|
||||
dev_err(drm->dev, "failed to find i2c slave encoder\n");
|
||||
/* Locate drm bridge from the hdmi encoder DT node */
|
||||
bridge = of_drm_find_bridge(np);
|
||||
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;
|
||||
}
|
||||
|
||||
driver =
|
||||
to_drm_i2c_encoder_driver(to_i2c_driver(i2c_slave->dev.driver));
|
||||
ret = driver->encoder_init(i2c_slave, drm, encoder);
|
||||
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,
|
||||
encoder->possible_crtcs = 1;
|
||||
encoder->possible_clones = 0;
|
||||
ret = drm_encoder_init(drm, encoder, &arcpgu_drm_encoder_funcs,
|
||||
DRM_MODE_ENCODER_TMDS, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_encoder_helper_add(&encoder->base,
|
||||
&arcpgu_drm_encoder_helper_funcs);
|
||||
/* Link drm_bridge to encoder */
|
||||
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;
|
||||
}
|
||||
ret = drm_bridge_attach(drm, bridge);
|
||||
if (ret)
|
||||
drm_encoder_cleanup(encoder);
|
||||
|
||||
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);
|
||||
if (ret < 0) {
|
||||
dev_err(drm->dev, "could not attach connector to encoder\n");
|
||||
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;
|
||||
}
|
||||
|
@ -25,8 +25,13 @@
|
||||
static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
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;
|
||||
|
||||
regmap_write(fsl_dev->regmap,
|
||||
DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
|
||||
|
||||
if (event) {
|
||||
crtc->state->event = NULL;
|
||||
|
||||
@ -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 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);
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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,
|
||||
.disable = fsl_dcu_drm_disable_crtc,
|
||||
.enable = fsl_dcu_drm_crtc_enable,
|
||||
.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)
|
||||
|
||||
regmap_write(fsl_dev->regmap, DCU_INT_STATUS, 0);
|
||||
regmap_write(fsl_dev->regmap, DCU_INT_MASK, ~0);
|
||||
regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
|
||||
DCU_UPDATE_MODE_READREG);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -139,8 +137,6 @@ static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
|
||||
drm_handle_vblank(dev, 0);
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -160,11 +160,6 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
|
||||
DCU_LAYER_POST_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;
|
||||
}
|
||||
|
@ -80,6 +80,7 @@ static void mtk_ovl_enable_vblank(struct mtk_ddp_comp *comp,
|
||||
ddp_comp);
|
||||
|
||||
priv->crtc = crtc;
|
||||
writel(0x0, comp->regs + DISP_REG_OVL_INTSTA);
|
||||
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,
|
||||
unsigned long pll_rate;
|
||||
unsigned int factor;
|
||||
|
||||
/* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */
|
||||
pix_rate = 1000UL * mode->clock;
|
||||
if (mode->clock <= 74000)
|
||||
if (mode->clock <= 27000)
|
||||
factor = 16 * 3;
|
||||
else if (mode->clock <= 84000)
|
||||
factor = 8 * 3;
|
||||
else
|
||||
else if (mode->clock <= 167000)
|
||||
factor = 4 * 3;
|
||||
else
|
||||
factor = 2 * 3;
|
||||
pll_rate = pix_rate * factor;
|
||||
|
||||
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,
|
||||
unsigned int bpc)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -217,6 +217,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
|
||||
if (ret < 0)
|
||||
goto err_component_unbind;
|
||||
|
||||
drm->vblank_disable_allowed = true;
|
||||
drm_kms_helper_poll_init(drm);
|
||||
drm_mode_config_reset(drm);
|
||||
|
||||
|
@ -1133,12 +1133,6 @@ static int mtk_hdmi_output_set_display_mode(struct mtk_hdmi *hdmi,
|
||||
phy_power_on(hdmi->phy);
|
||||
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_aud_unmute(hdmi);
|
||||
mtk_hdmi_hw_send_av_unmute(hdmi);
|
||||
@ -1401,6 +1395,16 @@ static void mtk_hdmi_bridge_pre_enable(struct drm_bridge *bridge)
|
||||
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)
|
||||
{
|
||||
struct mtk_hdmi *hdmi = hdmi_ctx_from_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_PIXEL]);
|
||||
phy_power_on(hdmi->phy);
|
||||
mtk_hdmi_send_infoframe(hdmi, &hdmi->mode);
|
||||
|
||||
hdmi->enabled = true;
|
||||
}
|
||||
|
@ -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);
|
||||
unsigned int pre_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__,
|
||||
rate, parent_rate);
|
||||
@ -298,18 +301,31 @@ static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
(0x1 << PLL_BR_SHIFT),
|
||||
RG_HDMITX_PLL_BP | RG_HDMITX_PLL_BC |
|
||||
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,
|
||||
(0x3 << PRD_IBIAS_CLK_SHIFT) |
|
||||
(0x3 << PRD_IBIAS_D2_SHIFT) |
|
||||
(0x3 << PRD_IBIAS_D1_SHIFT) |
|
||||
(0x3 << PRD_IBIAS_D0_SHIFT),
|
||||
(pre_ibias << PRD_IBIAS_CLK_SHIFT) |
|
||||
(pre_ibias << PRD_IBIAS_D2_SHIFT) |
|
||||
(pre_ibias << PRD_IBIAS_D1_SHIFT) |
|
||||
(pre_ibias << PRD_IBIAS_D0_SHIFT),
|
||||
RG_HDMITX_PRD_IBIAS_CLK |
|
||||
RG_HDMITX_PRD_IBIAS_D2 |
|
||||
RG_HDMITX_PRD_IBIAS_D1 |
|
||||
RG_HDMITX_PRD_IBIAS_D0);
|
||||
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,
|
||||
(hdmi_phy->drv_imp_clk << DRV_IMP_CLK_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,
|
||||
RG_HDMITX_DRV_IMP_CLK | RG_HDMITX_DRV_IMP_D2 |
|
||||
RG_HDMITX_DRV_IMP_D1 | RG_HDMITX_DRV_IMP_D0);
|
||||
mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON5,
|
||||
(hdmi_phy->ibias << DRV_IBIAS_CLK_SHIFT) |
|
||||
(hdmi_phy->ibias << DRV_IBIAS_D2_SHIFT) |
|
||||
(hdmi_phy->ibias << DRV_IBIAS_D1_SHIFT) |
|
||||
(hdmi_phy->ibias << DRV_IBIAS_D0_SHIFT),
|
||||
RG_HDMITX_DRV_IBIAS_CLK | RG_HDMITX_DRV_IBIAS_D2 |
|
||||
RG_HDMITX_DRV_IBIAS_D1 | RG_HDMITX_DRV_IBIAS_D0);
|
||||
(hdmi_ibias << DRV_IBIAS_CLK_SHIFT) |
|
||||
(hdmi_ibias << DRV_IBIAS_D2_SHIFT) |
|
||||
(hdmi_ibias << DRV_IBIAS_D1_SHIFT) |
|
||||
(hdmi_ibias << DRV_IBIAS_D0_SHIFT),
|
||||
RG_HDMITX_DRV_IBIAS_CLK |
|
||||
RG_HDMITX_DRV_IBIAS_D2 |
|
||||
RG_HDMITX_DRV_IBIAS_D1 |
|
||||
RG_HDMITX_DRV_IBIAS_D0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -142,9 +142,9 @@ static int sun4i_drv_bind(struct device *dev)
|
||||
|
||||
/* Create our layers */
|
||||
drv->layers = sun4i_layers_init(drm);
|
||||
if (!drv->layers) {
|
||||
if (IS_ERR(drv->layers)) {
|
||||
dev_err(drm->dev, "Couldn't create the planes\n");
|
||||
ret = -EINVAL;
|
||||
ret = PTR_ERR(drv->layers);
|
||||
goto free_drm;
|
||||
}
|
||||
|
||||
|
@ -152,15 +152,13 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder)
|
||||
|
||||
DRM_DEBUG_DRIVER("Enabling RGB output\n");
|
||||
|
||||
if (!IS_ERR(tcon->panel)) {
|
||||
if (!IS_ERR(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);
|
||||
|
||||
if (!IS_ERR(tcon->panel))
|
||||
drm_panel_enable(tcon->panel);
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
if (!IS_ERR(tcon->panel))
|
||||
drm_panel_disable(tcon->panel);
|
||||
|
||||
sun4i_tcon_channel_disable(tcon, 0);
|
||||
|
||||
/* encoder->bridge can be NULL; drm_bridge_disable checks for it */
|
||||
drm_bridge_disable(encoder->bridge);
|
||||
|
||||
if (!IS_ERR(tcon->panel)) {
|
||||
drm_panel_disable(tcon->panel);
|
||||
if (!IS_ERR(tcon->panel))
|
||||
drm_panel_unprepare(tcon->panel);
|
||||
}
|
||||
}
|
||||
|
||||
static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
|
||||
|
Loading…
Reference in New Issue
Block a user