Commit a6e434e9 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 8205ff1d 848819c5
...@@ -96,7 +96,7 @@ static void amdgpu_flip_work_func(struct work_struct *__work) ...@@ -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 * In practice this won't execute very often unless on very fast
* machines because the time window for this to happen is very small. * 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 /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
* start in hpos, and to the "fudged earlier" vblank start in * start in hpos, and to the "fudged earlier" vblank start in
* vpos. * vpos.
...@@ -112,13 +112,13 @@ static void amdgpu_flip_work_func(struct work_struct *__work) ...@@ -112,13 +112,13 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
break; break;
/* Sleep at least until estimated real start of hw vblank */ /* 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); min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
if (min_udelay > vblank->framedur_ns / 2000) { if (min_udelay > vblank->framedur_ns / 2000) {
/* Don't wait ridiculously long - something is wrong */ /* Don't wait ridiculously long - something is wrong */
repcnt = 0; repcnt = 0;
break; break;
} }
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
usleep_range(min_udelay, 2 * min_udelay); usleep_range(min_udelay, 2 * min_udelay);
spin_lock_irqsave(&crtc->dev->event_lock, flags); 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 ...@@ -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 max_lane_num = drm_dp_max_lane_count(dpcd);
unsigned lane_num, i, max_pix_clock; unsigned lane_num, i, max_pix_clock;
for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) { if (amdgpu_connector_encoder_get_dp_bridge_encoder_id(connector) ==
for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) { ENCODER_OBJECT_ID_NUTMEG) {
max_pix_clock = (lane_num * link_rates[i] * 8) / bpp; 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) { if (max_pix_clock >= pix_clock) {
*dp_lanes = lane_num; *dp_lanes = lane_num;
*dp_rate = link_rates[i]; *dp_rate = 270000;
return 0; 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; return -EINVAL;
......
...@@ -1382,8 +1382,16 @@ static void tda998x_connector_destroy(struct drm_connector *connector) ...@@ -1382,8 +1382,16 @@ static void tda998x_connector_destroy(struct drm_connector *connector)
drm_connector_cleanup(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 = { 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, .reset = drm_atomic_helper_connector_reset,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.detect = tda998x_connector_detect, .detect = tda998x_connector_detect,
......
...@@ -64,6 +64,7 @@ static void ipu_fb_enable(struct ipu_crtc *ipu_crtc) ...@@ -64,6 +64,7 @@ static void ipu_fb_enable(struct ipu_crtc *ipu_crtc)
/* Start DC channel and DI after IDMAC */ /* Start DC channel and DI after IDMAC */
ipu_dc_enable_channel(ipu_crtc->dc); ipu_dc_enable_channel(ipu_crtc->dc);
ipu_di_enable(ipu_crtc->di); ipu_di_enable(ipu_crtc->di);
drm_crtc_vblank_on(&ipu_crtc->base);
ipu_crtc->enabled = 1; ipu_crtc->enabled = 1;
} }
...@@ -80,6 +81,7 @@ static void ipu_fb_disable(struct ipu_crtc *ipu_crtc) ...@@ -80,6 +81,7 @@ static void ipu_fb_disable(struct ipu_crtc *ipu_crtc)
ipu_di_disable(ipu_crtc->di); ipu_di_disable(ipu_crtc->di);
ipu_plane_disable(ipu_crtc->plane[0]); ipu_plane_disable(ipu_crtc->plane[0]);
ipu_dc_disable(ipu); ipu_dc_disable(ipu);
drm_crtc_vblank_off(&ipu_crtc->base);
ipu_crtc->enabled = 0; ipu_crtc->enabled = 0;
} }
......
...@@ -42,6 +42,7 @@ static const uint32_t ipu_plane_formats[] = { ...@@ -42,6 +42,7 @@ static const uint32_t ipu_plane_formats[] = {
DRM_FORMAT_YVYU, DRM_FORMAT_YVYU,
DRM_FORMAT_YUV420, DRM_FORMAT_YUV420,
DRM_FORMAT_YVU420, DRM_FORMAT_YVU420,
DRM_FORMAT_RGB565,
}; };
int ipu_plane_irq(struct ipu_plane *ipu_plane) int ipu_plane_irq(struct ipu_plane *ipu_plane)
......
...@@ -315,15 +315,27 @@ int radeon_dp_get_dp_link_config(struct drm_connector *connector, ...@@ -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 max_lane_num = drm_dp_max_lane_count(dpcd);
unsigned lane_num, i, max_pix_clock; unsigned lane_num, i, max_pix_clock;
for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) { if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) { ENCODER_OBJECT_ID_NUTMEG) {
max_pix_clock = (lane_num * link_rates[i] * 8) / bpp; 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) { if (max_pix_clock >= pix_clock) {
*dp_lanes = lane_num; *dp_lanes = lane_num;
*dp_rate = link_rates[i]; *dp_rate = 270000;
return 0; 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; return -EINVAL;
......
...@@ -455,7 +455,7 @@ static void radeon_flip_work_func(struct work_struct *__work) ...@@ -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 * In practice this won't execute very often unless on very fast
* machines because the time window for this to happen is very small. * 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 /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
* start in hpos, and to the "fudged earlier" vblank start in * start in hpos, and to the "fudged earlier" vblank start in
* vpos. * vpos.
...@@ -471,13 +471,13 @@ static void radeon_flip_work_func(struct work_struct *__work) ...@@ -471,13 +471,13 @@ static void radeon_flip_work_func(struct work_struct *__work)
break; break;
/* Sleep at least until estimated real start of hw vblank */ /* 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); min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
if (min_udelay > vblank->framedur_ns / 2000) { if (min_udelay > vblank->framedur_ns / 2000) {
/* Don't wait ridiculously long - something is wrong */ /* Don't wait ridiculously long - something is wrong */
repcnt = 0; repcnt = 0;
break; break;
} }
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
usleep_range(min_udelay, 2 * min_udelay); usleep_range(min_udelay, 2 * min_udelay);
spin_lock_irqsave(&crtc->dev->event_lock, flags); spin_lock_irqsave(&crtc->dev->event_lock, flags);
}; };
......
...@@ -1079,6 +1079,8 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev) ...@@ -1079,6 +1079,8 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
/* update display watermarks based on new power state */ /* update display watermarks based on new power state */
radeon_bandwidth_update(rdev); radeon_bandwidth_update(rdev);
/* update displays */
radeon_dpm_display_configuration_changed(rdev);
/* wait for the rings to drain */ /* wait for the rings to drain */
for (i = 0; i < RADEON_NUM_RINGS; i++) { for (i = 0; i < RADEON_NUM_RINGS; i++) {
...@@ -1095,9 +1097,6 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev) ...@@ -1095,9 +1097,6 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
radeon_dpm_post_set_power_state(rdev); 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_crtcs = rdev->pm.dpm.new_active_crtcs;
rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count; rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count;
rdev->pm.dpm.single_display = single_display; rdev->pm.dpm.single_display = single_display;
......
...@@ -563,6 +563,8 @@ static void vmw_sou_connector_destroy(struct drm_connector *connector) ...@@ -563,6 +563,8 @@ static void vmw_sou_connector_destroy(struct drm_connector *connector)
static const struct drm_connector_funcs vmw_sou_connector_funcs = { static const struct drm_connector_funcs vmw_sou_connector_funcs = {
.dpms = vmw_du_connector_dpms, .dpms = vmw_du_connector_dpms,
.detect = vmw_du_connector_detect,
.fill_modes = vmw_du_connector_fill_modes,
.set_property = vmw_du_connector_set_property, .set_property = vmw_du_connector_set_property,
.destroy = vmw_sou_connector_destroy, .destroy = vmw_sou_connector_destroy,
}; };
......
...@@ -1050,6 +1050,17 @@ static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base) ...@@ -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++) { for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
const struct ipu_platform_reg *reg = &client_reg[i]; const struct ipu_platform_reg *reg = &client_reg[i];
struct platform_device *pdev; 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++); pdev = platform_device_alloc(reg->name, id++);
if (!pdev) { if (!pdev) {
...@@ -1057,17 +1068,9 @@ static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base) ...@@ -1057,17 +1068,9 @@ static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
goto err_register; goto err_register;
} }
pdev->dev.of_node = of_node;
pdev->dev.parent = dev; 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, &reg->pdata, ret = platform_device_add_data(pdev, &reg->pdata,
sizeof(reg->pdata)); sizeof(reg->pdata));
if (!ret) if (!ret)
...@@ -1289,10 +1292,6 @@ static int ipu_probe(struct platform_device *pdev) ...@@ -1289,10 +1292,6 @@ static int ipu_probe(struct platform_device *pdev)
ipu->irq_sync = irq_sync; ipu->irq_sync = irq_sync;
ipu->irq_err = irq_err; ipu->irq_err = irq_err;
ret = ipu_irq_init(ipu);
if (ret)
goto out_failed_irq;
ret = device_reset(&pdev->dev); ret = device_reset(&pdev->dev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to reset: %d\n", ret); dev_err(&pdev->dev, "failed to reset: %d\n", ret);
...@@ -1302,6 +1301,10 @@ static int ipu_probe(struct platform_device *pdev) ...@@ -1302,6 +1301,10 @@ static int ipu_probe(struct platform_device *pdev)
if (ret) if (ret)
goto out_failed_reset; 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 */ /* Set MCU_T to divide MCU access window into 2 */
ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18), ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
IPU_DISP_GEN); IPU_DISP_GEN);
...@@ -1324,9 +1327,9 @@ static int ipu_probe(struct platform_device *pdev) ...@@ -1324,9 +1327,9 @@ static int ipu_probe(struct platform_device *pdev)
failed_add_clients: failed_add_clients:
ipu_submodules_exit(ipu); ipu_submodules_exit(ipu);
failed_submodules_init: failed_submodules_init:
out_failed_reset:
ipu_irq_exit(ipu); ipu_irq_exit(ipu);
out_failed_irq: out_failed_irq:
out_failed_reset:
clk_disable_unprepare(ipu->clk); clk_disable_unprepare(ipu->clk);
return ret; return ret;
} }
......
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