diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c | 73 | 
1 files changed, 46 insertions, 27 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c index ac9a8cd21c4b..d99c8779b51e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c @@ -16,6 +16,8 @@  #include "ivsrcid/ivsrcid_vislands30.h"  #include "amdgpu_vkms.h"  #include "amdgpu_display.h" +#include "atom.h" +#include "amdgpu_irq.h"  /**   * DOC: amdgpu_vkms @@ -41,16 +43,16 @@ static const u32 amdgpu_vkms_formats[] = {  static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct hrtimer *timer)  { -	struct amdgpu_vkms_output *output = container_of(timer, -							 struct amdgpu_vkms_output, -							 vblank_hrtimer); -	struct drm_crtc *crtc = &output->crtc; +	struct amdgpu_crtc *amdgpu_crtc = container_of(timer, struct amdgpu_crtc, vblank_timer); +	struct drm_crtc *crtc = &amdgpu_crtc->base; +	struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);  	u64 ret_overrun;  	bool ret; -	ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer, +	ret_overrun = hrtimer_forward_now(&amdgpu_crtc->vblank_timer,  					  output->period_ns); -	WARN_ON(ret_overrun != 1); +	if (ret_overrun != 1) +		DRM_WARN("%s: vblank timer overrun\n", __func__);  	ret = drm_crtc_handle_vblank(crtc);  	if (!ret) @@ -65,22 +67,21 @@ static int amdgpu_vkms_enable_vblank(struct drm_crtc *crtc)  	unsigned int pipe = drm_crtc_index(crtc);  	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];  	struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc); +	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);  	drm_calc_timestamping_constants(crtc, &crtc->mode); -	hrtimer_init(&out->vblank_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); -	out->vblank_hrtimer.function = &amdgpu_vkms_vblank_simulate;  	out->period_ns = ktime_set(0, vblank->framedur_ns); -	hrtimer_start(&out->vblank_hrtimer, out->period_ns, HRTIMER_MODE_REL); +	hrtimer_start(&amdgpu_crtc->vblank_timer, out->period_ns, HRTIMER_MODE_REL);  	return 0;  }  static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc)  { -	struct amdgpu_vkms_output *out = drm_crtc_to_amdgpu_vkms_output(crtc); +	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); -	hrtimer_cancel(&out->vblank_hrtimer); +	hrtimer_cancel(&amdgpu_crtc->vblank_timer);  }  static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc, @@ -92,13 +93,14 @@ static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,  	unsigned int pipe = crtc->index;  	struct amdgpu_vkms_output *output = drm_crtc_to_amdgpu_vkms_output(crtc);  	struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; +	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);  	if (!READ_ONCE(vblank->enabled)) {  		*vblank_time = ktime_get();  		return true;  	} -	*vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires); +	*vblank_time = READ_ONCE(amdgpu_crtc->vblank_timer.node.expires);  	if (WARN_ON(*vblank_time == vblank->time))  		return true; @@ -142,15 +144,16 @@ static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,  static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,  					  struct drm_atomic_state *state)  { +	unsigned long flags;  	if (crtc->state->event) { -		spin_lock(&crtc->dev->event_lock); +		spin_lock_irqsave(&crtc->dev->event_lock, flags);  		if (drm_crtc_vblank_get(crtc) != 0)  			drm_crtc_send_vblank_event(crtc, crtc->state->event);  		else  			drm_crtc_arm_vblank_event(crtc, crtc->state->event); -		spin_unlock(&crtc->dev->event_lock); +		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);  		crtc->state->event = NULL;  	} @@ -165,6 +168,8 @@ static const struct drm_crtc_helper_funcs amdgpu_vkms_crtc_helper_funcs = {  static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,  			  struct drm_plane *primary, struct drm_plane *cursor)  { +	struct amdgpu_device *adev = drm_to_adev(dev); +	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);  	int ret;  	ret = drm_crtc_init_with_planes(dev, crtc, primary, cursor, @@ -176,6 +181,17 @@ static int amdgpu_vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,  	drm_crtc_helper_add(crtc, &amdgpu_vkms_crtc_helper_funcs); +	amdgpu_crtc->crtc_id = drm_crtc_index(crtc); +	adev->mode_info.crtcs[drm_crtc_index(crtc)] = amdgpu_crtc; + +	amdgpu_crtc->pll_id = ATOM_PPLL_INVALID; +	amdgpu_crtc->encoder = NULL; +	amdgpu_crtc->connector = NULL; +	amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE; + +	hrtimer_init(&amdgpu_crtc->vblank_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); +	amdgpu_crtc->vblank_timer.function = &amdgpu_vkms_vblank_simulate; +  	return ret;  } @@ -375,6 +391,7 @@ static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,  						int index)  {  	struct drm_plane *plane; +	uint64_t modifiers[] = {DRM_FORMAT_MOD_LINEAR, DRM_FORMAT_MOD_INVALID};  	int ret;  	plane = kzalloc(sizeof(*plane), GFP_KERNEL); @@ -385,7 +402,7 @@ static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,  				       &amdgpu_vkms_plane_funcs,  				       amdgpu_vkms_formats,  				       ARRAY_SIZE(amdgpu_vkms_formats), -				       NULL, type, NULL); +				       modifiers, type, NULL);  	if (ret) {  		kfree(plane);  		return ERR_PTR(ret); @@ -396,12 +413,12 @@ static struct drm_plane *amdgpu_vkms_plane_init(struct drm_device *dev,  	return plane;  } -int amdgpu_vkms_output_init(struct drm_device *dev, -			    struct amdgpu_vkms_output *output, int index) +static int amdgpu_vkms_output_init(struct drm_device *dev, struct +				   amdgpu_vkms_output *output, int index)  {  	struct drm_connector *connector = &output->connector;  	struct drm_encoder *encoder = &output->encoder; -	struct drm_crtc *crtc = &output->crtc; +	struct drm_crtc *crtc = &output->crtc.base;  	struct drm_plane *primary, *cursor = NULL;  	int ret; @@ -465,6 +482,11 @@ static int amdgpu_vkms_sw_init(void *handle)  	int r, i;  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; +	adev->amdgpu_vkms_output = kcalloc(adev->mode_info.num_crtc, +		sizeof(struct amdgpu_vkms_output), GFP_KERNEL); +	if (!adev->amdgpu_vkms_output) +		return -ENOMEM; +  	adev_to_drm(adev)->max_vblank_count = 0;  	adev_to_drm(adev)->mode_config.funcs = &amdgpu_vkms_mode_funcs; @@ -481,10 +503,6 @@ static int amdgpu_vkms_sw_init(void *handle)  	if (r)  		return r; -	adev->amdgpu_vkms_output = kcalloc(adev->mode_info.num_crtc, sizeof(struct amdgpu_vkms_output), GFP_KERNEL); -	if (!adev->amdgpu_vkms_output) -		return -ENOMEM; -  	/* allocate crtcs, encoders, connectors */  	for (i = 0; i < adev->mode_info.num_crtc; i++) {  		r = amdgpu_vkms_output_init(adev_to_drm(adev), &adev->amdgpu_vkms_output[i], i); @@ -504,15 +522,16 @@ static int amdgpu_vkms_sw_fini(void *handle)  	int i = 0;  	for (i = 0; i < adev->mode_info.num_crtc; i++) -		if (adev->amdgpu_vkms_output[i].vblank_hrtimer.function) -			hrtimer_cancel(&adev->amdgpu_vkms_output[i].vblank_hrtimer); - -	kfree(adev->mode_info.bios_hardcoded_edid); -	kfree(adev->amdgpu_vkms_output); +		if (adev->mode_info.crtcs[i]) +			hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer);  	drm_kms_helper_poll_fini(adev_to_drm(adev)); +	drm_mode_config_cleanup(adev_to_drm(adev));  	adev->mode_info.mode_config_initialized = false; + +	kfree(adev->mode_info.bios_hardcoded_edid); +	kfree(adev->amdgpu_vkms_output);  	return 0;  } |