Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d64a1661 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'sti-drm-next-2017-01-06' of https://github.com/vinceab/linux into drm-next

stih410 cleanup, create fbdev at binding, HQVDP fixes.

* tag 'sti-drm-next-2017-01-06' of https://github.com/vinceab/linux:
  drm/sti: sti_vtg: Handle return NULL error from devm_ioremap_nocache
  drm/sti: remove deprecated sti_vtac.c file
  drm/sti: create fbdev at binding
  drm/sti: update fps debugfs entries
  drm/sti: do not post HQVDP command if no update
  drm/sti: load XP70 firmware only once
  drm/sti: allow audio playback on HDMI even if disabled.
parents 282d0a35 1ae0d5af
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -13,7 +13,6 @@ sti-drm-y := \
	sti_dvo.o \
	sti_awg_utils.o \
	sti_vtg.o \
	sti_vtac.o \
	sti_hda.o \
	sti_tvout.o \
	sti_hqvdp.o \
+14 −14
Original line number Diff line number Diff line
@@ -252,19 +252,7 @@ static void sti_output_poll_changed(struct drm_device *ddev)
{
	struct sti_private *private = ddev->dev_private;

	if (!ddev->mode_config.num_connector)
		return;

	if (private->fbdev) {
	drm_fbdev_cma_hotplug_event(private->fbdev);
		return;
	}

	private->fbdev = drm_fbdev_cma_init(ddev, 32,
					    ddev->mode_config.num_crtc,
					    ddev->mode_config.num_connector);
	if (IS_ERR(private->fbdev))
		private->fbdev = NULL;
}

static const struct drm_mode_config_funcs sti_mode_config_funcs = {
@@ -382,6 +370,8 @@ static void sti_cleanup(struct drm_device *ddev)
static int sti_bind(struct device *dev)
{
	struct drm_device *ddev;
	struct sti_private *private;
	struct drm_fbdev_cma *fbdev;
	int ret;

	ddev = drm_dev_alloc(&sti_driver, dev);
@@ -404,6 +394,17 @@ static int sti_bind(struct device *dev)

	drm_mode_config_reset(ddev);

	private = ddev->dev_private;
	if (ddev->mode_config.num_connector) {
		fbdev = drm_fbdev_cma_init(ddev, 32, ddev->mode_config.num_crtc,
					   ddev->mode_config.num_connector);
		if (IS_ERR(fbdev)) {
			DRM_DEBUG_DRIVER("Warning: fails to create fbdev\n");
			fbdev = NULL;
		}
		private->fbdev = fbdev;
	}

	return 0;

err_register:
@@ -476,7 +477,6 @@ static struct platform_driver sti_platform_driver = {

static struct platform_driver * const drivers[] = {
	&sti_tvout_driver,
	&sti_vtac_driver,
	&sti_hqvdp_driver,
	&sti_hdmi_driver,
	&sti_hda_driver,
+0 −1
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@ struct sti_private {
};

extern struct platform_driver sti_tvout_driver;
extern struct platform_driver sti_vtac_driver;
extern struct platform_driver sti_hqvdp_driver;
extern struct platform_driver sti_hdmi_driver;
extern struct platform_driver sti_hda_driver;
+101 −104
Original line number Diff line number Diff line
@@ -788,6 +788,95 @@ static void sti_hdmi_disable(struct drm_bridge *bridge)
	hdmi->enabled = false;
}

/**
 * sti_hdmi_audio_get_non_coherent_n() - get N parameter for non-coherent
 * clocks. None-coherent clocks means that audio and TMDS clocks have not the
 * same source (drifts between clocks). In this case assumption is that CTS is
 * automatically calculated by hardware.
 *
 * @audio_fs: audio frame clock frequency in Hz
 *
 * Values computed are based on table described in HDMI specification 1.4b
 *
 * Returns n value.
 */
static int sti_hdmi_audio_get_non_coherent_n(unsigned int audio_fs)
{
	unsigned int n;

	switch (audio_fs) {
	case 32000:
		n = 4096;
		break;
	case 44100:
		n = 6272;
		break;
	case 48000:
		n = 6144;
		break;
	case 88200:
		n = 6272 * 2;
		break;
	case 96000:
		n = 6144 * 2;
		break;
	case 176400:
		n = 6272 * 4;
		break;
	case 192000:
		n = 6144 * 4;
		break;
	default:
		/* Not pre-defined, recommended value: 128 * fs / 1000 */
		n = (audio_fs * 128) / 1000;
	}

	return n;
}

static int hdmi_audio_configure(struct sti_hdmi *hdmi)
{
	int audio_cfg, n;
	struct hdmi_audio_params *params = &hdmi->audio;
	struct hdmi_audio_infoframe *info = &params->cea;

	DRM_DEBUG_DRIVER("\n");

	if (!hdmi->enabled)
		return 0;

	/* update N parameter */
	n = sti_hdmi_audio_get_non_coherent_n(params->sample_rate);

	DRM_DEBUG_DRIVER("Audio rate = %d Hz, TMDS clock = %d Hz, n = %d\n",
			 params->sample_rate, hdmi->mode.clock * 1000, n);
	hdmi_write(hdmi, n, HDMI_AUDN);

	/* update HDMI registers according to configuration */
	audio_cfg = HDMI_AUD_CFG_SPDIF_DIV_2 | HDMI_AUD_CFG_DTS_INVALID |
		    HDMI_AUD_CFG_ONE_BIT_INVALID;

	switch (info->channels) {
	case 8:
		audio_cfg |= HDMI_AUD_CFG_CH78_VALID;
	case 6:
		audio_cfg |= HDMI_AUD_CFG_CH56_VALID;
	case 4:
		audio_cfg |= HDMI_AUD_CFG_CH34_VALID | HDMI_AUD_CFG_8CH;
	case 2:
		audio_cfg |= HDMI_AUD_CFG_CH12_VALID;
		break;
	default:
		DRM_ERROR("ERROR: Unsupported number of channels (%d)!\n",
			  info->channels);
		return -EINVAL;
	}

	hdmi_write(hdmi, audio_cfg, HDMI_AUDIO_CFG);

	return hdmi_audio_infoframe_config(hdmi);
}

static void sti_hdmi_pre_enable(struct drm_bridge *bridge)
{
	struct sti_hdmi *hdmi = bridge->driver_private;
@@ -826,9 +915,12 @@ static void sti_hdmi_pre_enable(struct drm_bridge *bridge)
	if (hdmi_avi_infoframe_config(hdmi))
		DRM_ERROR("Unable to configure AVI infoframe\n");

	/* Program AUDIO infoframe */
	if (hdmi_audio_infoframe_config(hdmi))
		DRM_ERROR("Unable to configure AUDIO infoframe\n");
	if (hdmi->audio.enabled) {
		if (hdmi_audio_configure(hdmi))
			DRM_ERROR("Unable to configure audio\n");
	} else {
		hdmi_audio_infoframe_config(hdmi);
	}

	/* Program VS infoframe */
	if (hdmi_vendor_infoframe_config(hdmi))
@@ -1078,97 +1170,6 @@ static struct drm_encoder *sti_hdmi_find_encoder(struct drm_device *dev)
	return NULL;
}

/**
 * sti_hdmi_audio_get_non_coherent_n() - get N parameter for non-coherent
 * clocks. None-coherent clocks means that audio and TMDS clocks have not the
 * same source (drifts between clocks). In this case assumption is that CTS is
 * automatically calculated by hardware.
 *
 * @audio_fs: audio frame clock frequency in Hz
 *
 * Values computed are based on table described in HDMI specification 1.4b
 *
 * Returns n value.
 */
static int sti_hdmi_audio_get_non_coherent_n(unsigned int audio_fs)
{
	unsigned int n;

	switch (audio_fs) {
	case 32000:
		n = 4096;
		break;
	case 44100:
		n = 6272;
		break;
	case 48000:
		n = 6144;
		break;
	case 88200:
		n = 6272 * 2;
		break;
	case 96000:
		n = 6144 * 2;
		break;
	case 176400:
		n = 6272 * 4;
		break;
	case 192000:
		n = 6144 * 4;
		break;
	default:
		/* Not pre-defined, recommended value: 128 * fs / 1000 */
		n = (audio_fs * 128) / 1000;
	}

	return n;
}

static int hdmi_audio_configure(struct sti_hdmi *hdmi,
				struct hdmi_audio_params *params)
{
	int audio_cfg, n;
	struct hdmi_audio_infoframe *info = &params->cea;

	DRM_DEBUG_DRIVER("\n");

	if (!hdmi->enabled)
		return 0;

	/* update N parameter */
	n = sti_hdmi_audio_get_non_coherent_n(params->sample_rate);

	DRM_DEBUG_DRIVER("Audio rate = %d Hz, TMDS clock = %d Hz, n = %d\n",
			 params->sample_rate, hdmi->mode.clock * 1000, n);
	hdmi_write(hdmi, n, HDMI_AUDN);

	/* update HDMI registers according to configuration */
	audio_cfg = HDMI_AUD_CFG_SPDIF_DIV_2 | HDMI_AUD_CFG_DTS_INVALID |
		    HDMI_AUD_CFG_ONE_BIT_INVALID;

	switch (info->channels) {
	case 8:
		audio_cfg |= HDMI_AUD_CFG_CH78_VALID;
	case 6:
		audio_cfg |= HDMI_AUD_CFG_CH56_VALID;
	case 4:
		audio_cfg |= HDMI_AUD_CFG_CH34_VALID | HDMI_AUD_CFG_8CH;
	case 2:
		audio_cfg |= HDMI_AUD_CFG_CH12_VALID;
		break;
	default:
		DRM_ERROR("ERROR: Unsupported number of channels (%d)!\n",
			  info->channels);
		return -EINVAL;
	}

	hdmi_write(hdmi, audio_cfg, HDMI_AUDIO_CFG);

	hdmi->audio = *params;

	return hdmi_audio_infoframe_config(hdmi);
}

static void hdmi_audio_shutdown(struct device *dev, void *data)
{
	struct sti_hdmi *hdmi = dev_get_drvdata(dev);
@@ -1192,17 +1193,9 @@ static int hdmi_audio_hw_params(struct device *dev,
{
	struct sti_hdmi *hdmi = dev_get_drvdata(dev);
	int ret;
	struct hdmi_audio_params audio = {
		.sample_width = params->sample_width,
		.sample_rate = params->sample_rate,
		.cea = params->cea,
	};

	DRM_DEBUG_DRIVER("\n");

	if (!hdmi->enabled)
		return 0;

	if ((daifmt->fmt != HDMI_I2S) || daifmt->bit_clk_inv ||
	    daifmt->frame_clk_inv || daifmt->bit_clk_master ||
	    daifmt->frame_clk_master) {
@@ -1213,9 +1206,13 @@ static int hdmi_audio_hw_params(struct device *dev,
		return -EINVAL;
	}

	audio.enabled = true;
	hdmi->audio.sample_width = params->sample_width;
	hdmi->audio.sample_rate = params->sample_rate;
	hdmi->audio.cea = params->cea;

	hdmi->audio.enabled = true;

	ret = hdmi_audio_configure(hdmi, &audio);
	ret = hdmi_audio_configure(hdmi);
	if (ret < 0)
		return ret;

+21 −2
Original line number Diff line number Diff line
@@ -332,6 +332,7 @@ struct sti_hqvdp_cmd {
 * @hqvdp_cmd_paddr:   physical address of hqvdp_cmd
 * @vtg:               vtg for main data path
 * @xp70_initialized:  true if xp70 is already initialized
 * @vtg_registered:    true if registered to VTG
 */
struct sti_hqvdp {
	struct device *dev;
@@ -347,6 +348,7 @@ struct sti_hqvdp {
	u32 hqvdp_cmd_paddr;
	struct sti_vtg *vtg;
	bool xp70_initialized;
	bool vtg_registered;
};

#define to_sti_hqvdp(x) container_of(x, struct sti_hqvdp, plane)
@@ -771,7 +773,7 @@ static void sti_hqvdp_disable(struct sti_hqvdp *hqvdp)
		DRM_ERROR("XP70 could not revert to idle\n");

	hqvdp->plane.status = STI_PLANE_DISABLED;
	hqvdp->xp70_initialized = false;
	hqvdp->vtg_registered = false;
}

/**
@@ -1064,10 +1066,11 @@ static int sti_hqvdp_atomic_check(struct drm_plane *drm_plane,
		return -EINVAL;
	}

	if (!hqvdp->xp70_initialized) {
	if (!hqvdp->xp70_initialized)
		/* Start HQVDP XP70 coprocessor */
		sti_hqvdp_start_xp70(hqvdp);

	if (!hqvdp->vtg_registered) {
		/* Prevent VTG shutdown */
		if (clk_prepare_enable(hqvdp->clk_pix_main)) {
			DRM_ERROR("Failed to prepare/enable pix main clk\n");
@@ -1081,6 +1084,7 @@ static int sti_hqvdp_atomic_check(struct drm_plane *drm_plane,
			DRM_ERROR("Cannot register VTG notifier\n");
			return -EINVAL;
		}
		hqvdp->vtg_registered = true;
	}

	DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
@@ -1113,6 +1117,21 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
	if (!crtc || !fb)
		return;

	if ((oldstate->fb == state->fb) &&
	    (oldstate->crtc_x == state->crtc_x) &&
	    (oldstate->crtc_y == state->crtc_y) &&
	    (oldstate->crtc_w == state->crtc_w) &&
	    (oldstate->crtc_h == state->crtc_h) &&
	    (oldstate->src_x == state->src_x) &&
	    (oldstate->src_y == state->src_y) &&
	    (oldstate->src_w == state->src_w) &&
	    (oldstate->src_h == state->src_h)) {
		/* No change since last update, do not post cmd */
		DRM_DEBUG_DRIVER("No change, not posting cmd\n");
		plane->status = STI_PLANE_UPDATED;
		return;
	}

	mode = &crtc->mode;
	dst_x = state->crtc_x;
	dst_y = state->crtc_y;
Loading