Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Pull drm fixes from Dave Airlie: "A few imx fixes I missed from a couple of weeks ago, they still aren't that big and fix some regression and a fail to boot problem. Other than that, a couple of regression fixes for radeon/amdgpu, one regression fix for vmwgfx and one regression fix for tda998x" * 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: Revert "drm/radeon/pm: adjust display configuration after powerstate" drm/amdgpu/dp: add back special handling for NUTMEG drm/radeon/dp: add back special handling for NUTMEG drm/i2c: tda998x: Choose between atomic or non atomic dpms helper drm/vmwgfx: Add back ->detect() and ->fill_modes() drm/radeon: Fix error handling in radeon_flip_work_func. drm/amdgpu: Fix error handling in amdgpu_flip_work_func. drm/imx: Add missing DRM_FORMAT_RGB565 to ipu_plane_formats drm/imx: notify DRM core about CRTC vblank state gpu: ipu-v3: Reset IPU before activating IRQ gpu: ipu-v3: Do not bail out on missing optional port nodes
This commit is contained in:
commit
a6e434e955
|
@ -96,7 +96,7 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
|
|||
* In practice this won't execute very often unless on very fast
|
||||
* machines because the time window for this to happen is very small.
|
||||
*/
|
||||
while (amdgpuCrtc->enabled && repcnt--) {
|
||||
while (amdgpuCrtc->enabled && --repcnt) {
|
||||
/* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
|
||||
* start in hpos, and to the "fudged earlier" vblank start in
|
||||
* vpos.
|
||||
|
@ -112,13 +112,13 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
|
|||
break;
|
||||
|
||||
/* Sleep at least until estimated real start of hw vblank */
|
||||
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
|
||||
min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
|
||||
if (min_udelay > vblank->framedur_ns / 2000) {
|
||||
/* Don't wait ridiculously long - something is wrong */
|
||||
repcnt = 0;
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
|
||||
usleep_range(min_udelay, 2 * min_udelay);
|
||||
spin_lock_irqsave(&crtc->dev->event_lock, flags);
|
||||
};
|
||||
|
|
|
@ -265,15 +265,27 @@ static int amdgpu_atombios_dp_get_dp_link_config(struct drm_connector *connector
|
|||
unsigned max_lane_num = drm_dp_max_lane_count(dpcd);
|
||||
unsigned lane_num, i, max_pix_clock;
|
||||
|
||||
for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
|
||||
for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) {
|
||||
max_pix_clock = (lane_num * link_rates[i] * 8) / bpp;
|
||||
if (amdgpu_connector_encoder_get_dp_bridge_encoder_id(connector) ==
|
||||
ENCODER_OBJECT_ID_NUTMEG) {
|
||||
for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
|
||||
max_pix_clock = (lane_num * 270000 * 8) / bpp;
|
||||
if (max_pix_clock >= pix_clock) {
|
||||
*dp_lanes = lane_num;
|
||||
*dp_rate = link_rates[i];
|
||||
*dp_rate = 270000;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
|
||||
for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) {
|
||||
max_pix_clock = (lane_num * link_rates[i] * 8) / bpp;
|
||||
if (max_pix_clock >= pix_clock) {
|
||||
*dp_lanes = lane_num;
|
||||
*dp_rate = link_rates[i];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
|
|
|
@ -1382,8 +1382,16 @@ static void tda998x_connector_destroy(struct drm_connector *connector)
|
|||
drm_connector_cleanup(connector);
|
||||
}
|
||||
|
||||
static int tda998x_connector_dpms(struct drm_connector *connector, int mode)
|
||||
{
|
||||
if (drm_core_check_feature(connector->dev, DRIVER_ATOMIC))
|
||||
return drm_atomic_helper_connector_dpms(connector, mode);
|
||||
else
|
||||
return drm_helper_connector_dpms(connector, mode);
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs tda998x_connector_funcs = {
|
||||
.dpms = drm_atomic_helper_connector_dpms,
|
||||
.dpms = tda998x_connector_dpms,
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.detect = tda998x_connector_detect,
|
||||
|
|
|
@ -64,6 +64,7 @@ static void ipu_fb_enable(struct ipu_crtc *ipu_crtc)
|
|||
/* Start DC channel and DI after IDMAC */
|
||||
ipu_dc_enable_channel(ipu_crtc->dc);
|
||||
ipu_di_enable(ipu_crtc->di);
|
||||
drm_crtc_vblank_on(&ipu_crtc->base);
|
||||
|
||||
ipu_crtc->enabled = 1;
|
||||
}
|
||||
|
@ -80,6 +81,7 @@ static void ipu_fb_disable(struct ipu_crtc *ipu_crtc)
|
|||
ipu_di_disable(ipu_crtc->di);
|
||||
ipu_plane_disable(ipu_crtc->plane[0]);
|
||||
ipu_dc_disable(ipu);
|
||||
drm_crtc_vblank_off(&ipu_crtc->base);
|
||||
|
||||
ipu_crtc->enabled = 0;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ static const uint32_t ipu_plane_formats[] = {
|
|||
DRM_FORMAT_YVYU,
|
||||
DRM_FORMAT_YUV420,
|
||||
DRM_FORMAT_YVU420,
|
||||
DRM_FORMAT_RGB565,
|
||||
};
|
||||
|
||||
int ipu_plane_irq(struct ipu_plane *ipu_plane)
|
||||
|
|
|
@ -315,15 +315,27 @@ int radeon_dp_get_dp_link_config(struct drm_connector *connector,
|
|||
unsigned max_lane_num = drm_dp_max_lane_count(dpcd);
|
||||
unsigned lane_num, i, max_pix_clock;
|
||||
|
||||
for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
|
||||
for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) {
|
||||
max_pix_clock = (lane_num * link_rates[i] * 8) / bpp;
|
||||
if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
|
||||
ENCODER_OBJECT_ID_NUTMEG) {
|
||||
for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
|
||||
max_pix_clock = (lane_num * 270000 * 8) / bpp;
|
||||
if (max_pix_clock >= pix_clock) {
|
||||
*dp_lanes = lane_num;
|
||||
*dp_rate = link_rates[i];
|
||||
*dp_rate = 270000;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
|
||||
for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) {
|
||||
max_pix_clock = (lane_num * link_rates[i] * 8) / bpp;
|
||||
if (max_pix_clock >= pix_clock) {
|
||||
*dp_lanes = lane_num;
|
||||
*dp_rate = link_rates[i];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
|
|
|
@ -455,7 +455,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
|
|||
* In practice this won't execute very often unless on very fast
|
||||
* machines because the time window for this to happen is very small.
|
||||
*/
|
||||
while (radeon_crtc->enabled && repcnt--) {
|
||||
while (radeon_crtc->enabled && --repcnt) {
|
||||
/* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
|
||||
* start in hpos, and to the "fudged earlier" vblank start in
|
||||
* vpos.
|
||||
|
@ -471,13 +471,13 @@ static void radeon_flip_work_func(struct work_struct *__work)
|
|||
break;
|
||||
|
||||
/* Sleep at least until estimated real start of hw vblank */
|
||||
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
|
||||
min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
|
||||
if (min_udelay > vblank->framedur_ns / 2000) {
|
||||
/* Don't wait ridiculously long - something is wrong */
|
||||
repcnt = 0;
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
|
||||
usleep_range(min_udelay, 2 * min_udelay);
|
||||
spin_lock_irqsave(&crtc->dev->event_lock, flags);
|
||||
};
|
||||
|
|
|
@ -1079,6 +1079,8 @@ force:
|
|||
|
||||
/* update display watermarks based on new power state */
|
||||
radeon_bandwidth_update(rdev);
|
||||
/* update displays */
|
||||
radeon_dpm_display_configuration_changed(rdev);
|
||||
|
||||
/* wait for the rings to drain */
|
||||
for (i = 0; i < RADEON_NUM_RINGS; i++) {
|
||||
|
@ -1095,9 +1097,6 @@ force:
|
|||
|
||||
radeon_dpm_post_set_power_state(rdev);
|
||||
|
||||
/* update displays */
|
||||
radeon_dpm_display_configuration_changed(rdev);
|
||||
|
||||
rdev->pm.dpm.current_active_crtcs = rdev->pm.dpm.new_active_crtcs;
|
||||
rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count;
|
||||
rdev->pm.dpm.single_display = single_display;
|
||||
|
|
|
@ -563,6 +563,8 @@ static void vmw_sou_connector_destroy(struct drm_connector *connector)
|
|||
|
||||
static const struct drm_connector_funcs vmw_sou_connector_funcs = {
|
||||
.dpms = vmw_du_connector_dpms,
|
||||
.detect = vmw_du_connector_detect,
|
||||
.fill_modes = vmw_du_connector_fill_modes,
|
||||
.set_property = vmw_du_connector_set_property,
|
||||
.destroy = vmw_sou_connector_destroy,
|
||||
};
|
||||
|
|
|
@ -1050,6 +1050,17 @@ static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
|
|||
for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
|
||||
const struct ipu_platform_reg *reg = &client_reg[i];
|
||||
struct platform_device *pdev;
|
||||
struct device_node *of_node;
|
||||
|
||||
/* Associate subdevice with the corresponding port node */
|
||||
of_node = of_graph_get_port_by_id(dev->of_node, i);
|
||||
if (!of_node) {
|
||||
dev_info(dev,
|
||||
"no port@%d node in %s, not using %s%d\n",
|
||||
i, dev->of_node->full_name,
|
||||
(i / 2) ? "DI" : "CSI", i % 2);
|
||||
continue;
|
||||
}
|
||||
|
||||
pdev = platform_device_alloc(reg->name, id++);
|
||||
if (!pdev) {
|
||||
|
@ -1057,17 +1068,9 @@ static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
|
|||
goto err_register;
|
||||
}
|
||||
|
||||
pdev->dev.of_node = of_node;
|
||||
pdev->dev.parent = dev;
|
||||
|
||||
/* Associate subdevice with the corresponding port node */
|
||||
pdev->dev.of_node = of_graph_get_port_by_id(dev->of_node, i);
|
||||
if (!pdev->dev.of_node) {
|
||||
dev_err(dev, "missing port@%d node in %s\n", i,
|
||||
dev->of_node->full_name);
|
||||
ret = -ENODEV;
|
||||
goto err_register;
|
||||
}
|
||||
|
||||
ret = platform_device_add_data(pdev, ®->pdata,
|
||||
sizeof(reg->pdata));
|
||||
if (!ret)
|
||||
|
@ -1289,10 +1292,6 @@ static int ipu_probe(struct platform_device *pdev)
|
|||
ipu->irq_sync = irq_sync;
|
||||
ipu->irq_err = irq_err;
|
||||
|
||||
ret = ipu_irq_init(ipu);
|
||||
if (ret)
|
||||
goto out_failed_irq;
|
||||
|
||||
ret = device_reset(&pdev->dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to reset: %d\n", ret);
|
||||
|
@ -1302,6 +1301,10 @@ static int ipu_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto out_failed_reset;
|
||||
|
||||
ret = ipu_irq_init(ipu);
|
||||
if (ret)
|
||||
goto out_failed_irq;
|
||||
|
||||
/* Set MCU_T to divide MCU access window into 2 */
|
||||
ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
|
||||
IPU_DISP_GEN);
|
||||
|
@ -1324,9 +1327,9 @@ static int ipu_probe(struct platform_device *pdev)
|
|||
failed_add_clients:
|
||||
ipu_submodules_exit(ipu);
|
||||
failed_submodules_init:
|
||||
out_failed_reset:
|
||||
ipu_irq_exit(ipu);
|
||||
out_failed_irq:
|
||||
out_failed_reset:
|
||||
clk_disable_unprepare(ipu->clk);
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue